题目简单明了,给 n 个点 m 条边 输入整个有向图,输出最大流。
这里用的还是EK算法,用bfs 进行优化,原本的bfs 是设置图的层来避免反向走,而这里看了一下大牛们的新方法,用了一下父节点,用了这种方法,对每一个bfs到的点设置一下父节点,这样在寻找增广路的时候,从 end 开始反向寻找到起点,再记录下最大流。。
很巧妙。。。
以下是AC 代码
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn = 205;
const int inf = 0x3fffffff;
int mp[maxn][maxn];
int p[maxn];
int n,m;
bool bfs(int st,int en)
{
queue<int>q;
bool vis[maxn];
memset(vis,false,sizeof(vis));
memset(p,-1,sizeof(p));
q.push(st);
vis[st]=true;
while(q.size())
{
int e = q.front();
q.pop();
if(e==en)
return true;
for(int i=1;i<=n;i++)
{
if(mp[e][i]&&!vis[i])
{
vis[i]=true;
p[i]=e;
q.push(i);
}
}
}
return false;
}
int EK(int st, int en)
{
int u,flow=0,mn;
while(bfs(st,en))
{
mn = inf;
u = en;
while(p[u]!=-1)
{
mn = min(mn, mp[p[u]][u]);
u=p[u];
}
flow += mn;
u = en;
while(p[u]!=-1)
{
mp[p[u]][u] -= mn;
mp[u][p[u]] += mn;
u=p[u];
}
}
return flow;
}
int main()
{
int t,Case=0;
scanf("%d",&t);
while(t--)
{
printf("Case %d: ",++Case);
scanf("%d%d",&n,&m);
memset(mp,0,sizeof(mp));
int u,v,cost;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&cost);
mp[u][v]+=cost;
}
int ans=EK(1,n);
printf("%d\n",ans);
}
return 0;
}