题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入格式
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)
输出格式
一行,包含一个正整数,即为该网络的最大流。
输入输出样例
输入 #1
4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40
输出 #1
50
说明/提示
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=25
对于70%的数据:N<=200,M<=1000
对于100%的数据:N<=10000,M<=100000
样例说明:
题目中存在3条路径:
4-->2-->3,该路线可通过20的流量
4-->3,可通过20的流量
4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)
故流量总计20+20+10=50。输出50。
思路
Edmonds-Karp:每次从所有的边中寻找一条可增广的路径,将它进行增广,更新最大流。
代码
#include<bits/stdc++.h> #define N 10700 #define M 107000 #define inf 1<<29 using namespace std; struct node{ int y,z,next; }e[M*2]; int tot=1,head[N],maxflow=0; int n,m,s,t; void add(int x,int y,int z){ e[++tot].y=y;e[tot].z=z;e[tot].next=head[x];head[x]=tot; e[++tot].y=x;e[tot].z=0;e[tot].next=head[y];head[y]=tot; } int incf[N],v[N],pre[N]; bool bfs(){ memset(v,0,sizeof(v)); queue<int> q; q.push(s);v[s]=1; incf[s]=inf; while(q.size()){ int x=q.front();q.pop(); for(int i=head[x];i;i=e[i].next){ int y=e[i].y,z=e[i].z; if(z){ if(v[y]) continue; incf[y]=min(incf[x],z); pre[y]=i; q.push(y);v[y]=1; if(y==t) return 1; } } } return 0; } void update(){ int x=t; while(x!=s){ int i=pre[x]; e[i].z-=incf[t]; e[i^1].z+=incf[t]; x=e[i^1].y; } maxflow+=incf[t]; } int main() { int x,y,z; cin>>n>>m>>s>>t; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); } while(spfa()) update(); cout<<maxflow<<endl; return 0; }
思路
Dinic:由于E-K算法中需要遍历全图才更新一条,因此我们可以进行分层,将图进行分层后直接增广所有可行边。
代码
#include<bits/stdc++.h> #define N 10700 #define M 107000 #define inf 1<<29 using namespace std; struct node{ int y,z,next; }e[M*2]; int tot=1,head[N],maxflow=0; int n,m,s,t; void add(int x,int y,int z){ e[++tot].y=y;e[tot].z=z;e[tot].next=head[x];head[x]=tot; e[++tot].y=x;e[tot].z=0;e[tot].next=head[y];head[y]=tot; } queue<int> q; int d[N]; bool bfs(){ memset(d,0,sizeof(d)); while(q.size()) q.pop(); q.push(s);d[s]=1; while(q.size()){ int x=q.front();q.pop(); for(int i=head[x];i;i=e[i].next){ int y=e[i].y,z=e[i].z; if(z&&!d[y]){ q.push(y);d[y]=d[x]+1; if(y==t) return 1; } } } return 0; } int dinic(int x,int flow){ if(x==t) return flow; int rest=flow,k; for(int i=head[x];i;i=e[i].next){ int y=e[i].y,z=e[i].z; if(z&&d[y]==d[x]+1){ k=dinic(y,min(rest,z)); if(!k) d[y]=0; e[i].z-=k; e[i^1].z+=k; rest-=k; } } return flow-rest; } int main() { int x,y,z,flow=0; cin>>n>>m>>s>>t; for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); } while(bfs()) while(flow=dinic(s,inf)) maxflow+=flow; cout<<maxflow<<endl; return 0; }