2 3 2 1 2 1 2 3 1 3 3 1 2 1 2 3 1 1 3 1
Case 1: 1 Case 2: 2
#include<stdio.h> #include<string.h> #include<queue> using namespace std; #define captype int const int N = 210; const int MAX= 1<<30; struct EDG{ int to,nxt; captype c; //每条边的残留量 }edg[N*N]; int head[N],eid; captype vf[N]; //顶点的剩余流量 int h[N]; //顶点的高度 //int n; //顶点个总个数,包含源点与汇点 int min(int a,int b){return a>b?b:a; } void init(){ memset(head,-1,sizeof(head)); eid=0; } //添加 有向边 void addEdg(int u , int v, captype c){ edg[eid].to=v; edg[eid].nxt=head[u]; edg[eid].c=c; head[u]=eid++; edg[eid].to=u; edg[eid].nxt=head[v]; edg[eid].c=0; head[v]=eid++; } captype maxFlow(int sNode,int eNode,int n){//源点与汇点 captype minh,ans=0; queue<int>q; memset(h,0,sizeof(h)); memset(vf,0,sizeof(vf)); h[sNode]=n+1; //源点的高度 vf[sNode]=MAX; //源点的余流 q.push(sNode); while(!q.empty()){ int u=q.front(); q.pop(); minh=MAX; for(int i=head[u]; i!=-1; i=edg[i].nxt){ int v=edg[i].to; captype fp; if(edg[i].c<vf[u])fp=edg[i].c; else fp=vf[u]; if(fp>0 ){ minh=min(minh, h[v]); if(u==sNode || h[u]==h[v]+1){ edg[i].c-=fp; edg[i^1].c+=fp; //反向边,给个反回的通道 vf[u]-=fp; vf[v]+=fp; if(v==eNode) ans+=fp; //当到达汇点时,就加入最大流中 if(v!=sNode && v!=eNode ) //只有即不是源点,也不是汇点时才能进队列 q.push(v); } } if(vf[u]==0) break; //如果顶点的余流为0,则可以跳出for循环 } //如果不是源点(也非汇点),且顶点仍有余流,则重新标记 高度+1 入队 //这里赋值为最低的相邻顶点的高度高一个单位,也可以简单的在原高度+1 if(u!=sNode && vf[u]>0){ h[u] = minh + 1; q.push(u); } } return ans; } int main(){ int T,cas=0,n,m,a,b,c; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); init(); while(m--){ scanf("%d%d%d",&a,&b,&c); addEdg(a,b,c); } printf("Case %d: %d\n",++cas,maxFlow(1,n,n)); } }
原文地址:http://blog.csdn.net/u010372095/article/details/46446429