最大流问题
给你一个图,图中有多少个顶点、点与点之间的距离(边长)告诉你,求从S点到T点的最大流量是多少?
Sample Input
2
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1
3 2
1 2 1
2 3 1
3 3
1 2 1
2 3 1
1 3 1
Sample Output
Case 1: 1
Case 2: 2
Case 2: 2
#include<cstdio> #include<cstring> #include<climits> using namespace std; #define N 90005 #define M 4000005 #define INF INT_MAX int s,t,num,pre[N],dis[N],gap[N],head[N],cur[N]; struct node { int u,v,w; int next; }e[M]; inline void add(int u,int v,int w) { e[num].u=u; e[num].v=v; e[num].w=w; e[num].next=head[u]; head[u]=num++; } inline void addedge(int u,int v,int w) { add(u,v,w); add(v,u,0); } inline int max(int a,int b) { return a>b?a:b; } inline int min(int a,int b) { return a<b?a:b; } int isap(int s,int t,int n) { int top,mindis,maxflow=0,v,i,aug; bool flag; for(i=0;i<=n;i++) { cur[i]=head[i]; gap[i]=dis[i]=0; } top=pre[s]=s; aug=INF; while(dis[s]<n) { flag=0; for(i=cur[top];i!=-1;i=e[i].next) { v=e[i].v; if(e[i].w>0&&dis[top]==dis[v]+1) { flag=1; break; } } if(flag) { pre[v]=top; cur[top]=i; aug=min(aug,e[i].w); top=v; if(top==t) { while(top!=s) { top=pre[top]; e[cur[top]].w-=aug; e[cur[top]^1].w+=aug; } top=s; maxflow+=aug; aug=INF; } } else { if(--gap[dis[top]]==0) break; mindis=n; cur[top]=head[top]; for(i=head[top];i!=-1;i=e[i].next) { v=e[i].v; if(e[i].w>0&&dis[v]+1<mindis) { mindis=dis[v]+1; cur[top]=i; } } dis[top]=mindis; gap[mindis]++; if(top!=s) top=pre[top]; } } return maxflow; } void init() { num=0; memset(head,-1,sizeof(head)); } int main() { int nodenum,m,n,test; scanf("%d",&test); for(int ii=1;ii<=test;ii++) { scanf("%d%d",&n,&m); init(); while(m--) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } //source=1,sink=n,nodenum=n; int res=isap(1,n,n); printf("Case %d: %d\n",ii,res); } return 0; }
另一种方法:
#include <iostream> #include <queue> using namespace std; const int N = 210; const int INF = 0x7FFFFFFF; int n,m,map[N][N],path[N],flow[N],start,end; queue<int> q; int bfs(){ int i,t; while(!q.empty()) q.pop(); memset(path,-1,sizeof(path)); path[start]=0,flow[start]=INF; q.push(start); while(!q.empty()){ t=q.front(); q.pop(); if(t==end) break; for(i=1;i<=m;i++){ if(i!=start && path[i]==-1 && map[t][i]){ flow[i]=flow[t]<map[t][i]?flow[t]:map[t][i]; q.push(i); path[i]=t; } } } if(path[end]==-1) return -1; return flow[m]; //一次遍历之后的流量增量 } int Edmonds_Karp(){ int max_flow=0,step,now,pre; while((step=bfs())!=-1){ //找不到增路径时退出 max_flow+=step; now=end; while(now!=start){ pre=path[now]; map[pre][now]-=step; //更新正向边的实际容量 map[now][pre]+=step; //添加反向边 now=pre; } } return max_flow; } int main(){ int i,u,v,cost; while(scanf("%d %d",&m,&n)!=EOF){ if(!n&&!m) return 0 ; memset(map,0,sizeof(map)); for(i=0;i<n;i++){ scanf("%d %d %d",&u,&v,&cost); map[u][v]+=cost; //not just only one input } start=1,end=m; printf("%d\n",Edmonds_Karp()); } return 0; }