HDU - 6582 Path


传送门:HDU - 6582

思路分析

删掉一些边,使得$1$到$n$的最短路变长
很明显的最小割问题,可能删除的边一定是最短路上经过的边
那么怎么判断哪些边是最短路上的呢,连反向边
令$d1$为1到各个点的距离,$d2$为$n$到各个点的距离
比如一条边$u–v$边权为$w$
如果这条边是最短路上的边,那么一定满足$d1[u]+d2[v]+w==d1[n]$
将满足条件的点全部连边跑一遍最小割就行了

样例输入

1
3 4
1 2 1
2 3 1
1 3 2
1 3 3

样例输出

3

AC代码


#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <vector>
#include <string>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#define ls x<<1
#define rs x<<1|1
#define fi first
#define se second
#define ll long long
#define pb push_back
#define mp make_pair
#define fun function
#define vi vector<int>
#define lowbit(x) x&(-x)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);
#define int long long

using namespace std;

const int INF = 1e18;
const int N=1e5+10;

vector<pair<int,int>>e1[N],e2[N];

struct node {
    int v,w,next;
} e[N];


int cnt=1,head[N<<1],d1[N],d2[N],dep[N],vis[N];
int n,m;

void add(int u,int v,int w) {
    e[++cnt].v=v;
    e[cnt].w=w;
    e[cnt].next=head[u];
    head[u]=cnt;
}

void dij(int s,int *dis,vector<pair<int,int>> *edge) {
    for(int i=0;i<=n;i++){
        dis[i]=INF;
        vis[i]=0;
    }
    dis[s]=0;
    priority_queue<pair<int,int> > q;
    q.push(make_pair(-dis[s],s));
    while(!q.empty()) {
        int u=q.top().second;
        q.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(auto i:edge[u]) {
            int v=i.fi;
            int w=i.se;
            if(!vis[v]&&dis[v]>dis[u]+w) {
                dis[v]=dis[u]+w;
                q.push(make_pair(-dis[v],v));
            }
        }
    }
}

bool bfs(int s,int t) {
    queue<int>q;
    mem(dep,0); 
    dep[s]=1;  
    q.push(s);
    while(!q.empty()) {
        int u=q.front();
        q.pop();
        for(int i=head[u]; i ; i=e[i].next) {
            int v=e[i].v;
            int w=e[i].w;
            if(w && !dep[v]) { 
                dep[v]=dep[u]+1;
                q.push(v);
            }
        }
    }

    return dep[t];
}

int dfs(int u,int f,int t) {
    int fl=0;
    if(u==t)
        return f;
    for(int i=head[u]; i && f ; i=e[i].next) {
        int v=e[i].v;
        if(dep[v]==dep[u]+1 && e[i].w) { 
            int nx=dfs(v,min(f,e[i].w),t);
            e[i].w-=nx;
            e[i^1].w+=nx;
            f-=nx;
            fl+=nx;
        }
    }
    if(!fl)
        dep[u]=-2;
    return fl;

}

int dinic(int s,int t) {
    int ans=0;
    while(bfs(s,t))
        ans+=dfs(s,INF,t); 
    return ans;
}



signed main() {

#ifdef xiaofan
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif

    int t;
    scanf("%lld",&t);
    while(t--) {
        cnt=1;
        mem(head,0);
        scanf("%lld%lld",&n,&m);
        while(m--) {
            int u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            e1[u].push_back(mp(v,w));
            e2[v].push_back(mp(u,w));

        }
        dij(1,d1,e1);
        dij(n,d2,e2);
        if(d1[n]==INF) {
            puts("0");
            continue;
        }
        for(int u=1; u<=n; u++) {
            for(auto i:e1[u]) {
                int v=i.fi;
                int w=i.se;
                if(d1[u]+d2[v]+w==d1[n]) {
                    add(u,v,w);
                    add(v,u,0);
                }
            }
        }
        printf("%lld\n",dinic(1,n));
        for(int i=1;i<=n;i++){
            e1[i].clear();
            e2[i].clear();
        }

    }




    return 0;
}

文章作者: 小凡
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小凡 !
评论
  目录
隐藏
{% if theme.sakura.enable %}{% endif %}