模板题:洛谷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;
}