模板题:洛谷p3376
题目大意:
给出一个网络图,以及其源点和汇点,求出其网络最大流。
基本思路:
套模板
EK的时间复杂度O(V*E^2)
EK算法思路:
1.通过BFS拓展合法节点(每个节点在本次BFS中仅遍历一次),找到汇点,并记录每个节点的前面节点(pre)(若找不到增广路,算法结束)
2.通过BFS的记录,从汇点回溯回源点,记录下每条弧流量的**最小值**minn, ans += minn(否则就会超出某条边的限制流量)
3.将所有经过的边的流量减去minn,反向边加上minn
4.重复上述步骤,直到找不到增广路,算法结束。
代码如下:
#include<iostream> #include<string> #include<queue> #include<vector> #include<stack> #include<algorithm> #include<cstdio> #include<cmath> #include<cstring> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn =10000+10; int n,m,st,en; struct Flow{ int st,en,num; }flow[200000+10]; vector<int>gra[maxn]; bool vis[maxn]; int pre[maxn]; bool bfs(){ memset(vis,false,sizeof(vis)); vis[st]=true; queue<int>q; q.push(st); while(!q.empty()){ int qf=q.front(); q.pop(); int sz=gra[qf].size(); for(int i=0;i<sz;i++){ int id=gra[qf][i]; int v=flow[id].en; if(flow[id].num>0&&!vis[v]){ vis[v]=true; q.push(v); pre[v]=id; if(v==en){ return true; } } } } return false; } int EK(){ int max_flow=0; while(bfs()){ int _min=inf; for(int i=en;i!=st;i=flow[pre[i]].st){ _min=min(_min,flow[pre[i]].num); } for(int i=en;i!=st;i=flow[pre[i]].st){ flow[pre[i]].num-=_min; flow[pre[i]+m].num+=_min; } max_flow+=_min; } return max_flow; } int main(){ scanf("%d%d%d%d",&n,&m,&st,&en); for(int i=0;i<m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); flow[i].st=u; flow[i].en=v; flow[i].num=w; flow[i+m].st=v; flow[i+m].en=u; flow[i+m].num=0; gra[u].push_back(i); gra[v].push_back(i+m); } printf("%d\n",EK()); return 0; }