Smallest Minimum Cut HDU

来源:互联网 发布:网络语233是什么意思 编辑:程序博客网 时间:2024/05/18 13:48

结论题,加边的时候每个边容量扩大为cap*(Edge+1)+1,跑一边最大流%(Edge+1)就是最少边数了

证明一下就是一个容量为8的边和两个容量为4的边,扩大后只有堵住原先8才是最小的

新最大流:maxflow*(Edge+1)+最少割边数

#include<bits/stdc++.h>using namespace std;#define ll long longconst int maxn=2e5+7;const int inf=0x3f3f3f3f;int num_nodes;int tot;int d[maxn],cur[maxn],source,sink;int p[maxn],num[maxn],vis[maxn];struct EDGE{    int from,to,cap,flow;};vector<EDGE>edge;vector<int>G[maxn];void init(){    edge.clear();    for(int i=0;i<maxn;i++)G[i].clear();}void addedge(int u,int v,int w){    edge.push_back((EDGE){u,v,w,0});    edge.push_back((EDGE){v,u,0,0});    tot=edge.size();    G[u].push_back(tot-2);    G[v].push_back(tot-1);}int bfs(){    memset(vis,0,sizeof vis);    queue<int>Q;    Q.push(sink);    vis[sink]=1;    d[sink]=0;    while(!Q.empty()){        int u=Q.front();        Q.pop();        int sz=G[u].size();        for(int i=0;i<sz;++i){            EDGE &e=edge[G[u][i]^1];            if(!vis[e.from] && e.cap>e.flow){                vis[e.from]=1;                d[e.from]=d[u]+1;                Q.push(e.from);            }        }    }    return vis[source];}int augment(){    int u=sink,a=inf;    while(u!=source){        EDGE &e=edge[p[u]];        a=min(a,e.cap-e.flow);        u=edge[p[u]].from;    }    u=sink;    while(u!=source){        edge[p[u]].flow+=a;        edge[p[u]^1].flow-=a;        u=edge[p[u]].from;    }    return a;}int maxflow(){    int flow=0;    bfs();    memset(num,0,sizeof num);    for(int i=0;i<num_nodes;i++)num[d[i]]++;    int u=source;    memset(cur,0,sizeof cur);    while(d[source]<num_nodes){        if(u==sink){            flow+=augment();            u=source;        }        int advance=0;        int sz=G[u].size();        for(int i=cur[u];i<sz;i++){            EDGE &e=edge[G[u][i]];            if(e.cap>e.flow && d[u]==d[e.to]+1){                advance=1;                p[e.to]=G[u][i];                cur[u]=i;                u=e.to;                break;            }        }        if(!advance){            int m=num_nodes-1;            int sz=G[u].size();            for(int i=0;i<sz;i++){                if(edge[G[u][i]].cap>edge[G[u][i]].flow){                    m=min(m,d[edge[G[u][i]].to]);                }                        }            if(--num[d[u]]==0)break;            num[d[u]=m+1]++;            cur[u]=0;            if(u!=source)u=edge[p[u]].from;        }    }    return flow;}int main(){    int T;scanf("%d",&T);    while(T--){        init();        int n,m;scanf("%d%d",&n,&m);        num_nodes=n+10;        scanf("%d%d",&source,&sink);        for(int i=1,u,v,w;i<=m;i++){            scanf("%d%d%d",&u,&v,&w);            addedge(u,v,w*(m+1)+1);//addedge(v,u,w*(m+1)+1);        }        printf("%d\n",maxflow()%(m+1));    }}