最大网络流C++(多看多理解)
作者:
Bonker
,
2021-12-17 22:55:12
,
所有人可见
,
阅读 455
//ek算法
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
long long n,m;
long long pre[5000];// 从 s - t 中的一个可行流中, 节点 i 的前序节点为 Pre[i];
long long vis[5000]; // 标记一个点是否被放进了队列
long long mp[300][300];// 记录图信息
bool bfs(long long s, long long t)
{
queue <long long > que;
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
pre[s] = s;
vis[s] = true;
que.push(s);//把源点放进队列
while(!que.empty())//bfs,找一条s到t的一条路(每条边的权值>0)
{
long long u = que.front();
que.pop();
for(long long i = 1; i <= n; i++)
{
if(mp[u][i] && !vis[i])//把与此点一步可达的点放进队列
{
pre[i] = u;//存入其前驱节点
vis[i] = 1;//标记此点
if(i == t)//已经找到了一条增广路
return true;
que.push(i);
}
}
}
return 0;//已经没有可以走的路
}
long long EK(long long s, long long t)
{
long long ans = 0;
while(bfs(s, t))//如果当前还有增广路
{
long long mi = 0x3f3f3f3f;
for(long long i = t; i != s; i = pre[i])
{
mi = min(mi, mp[pre[i]][i]);//找到此路上的边的最小权值
}
for(long long i = t; i != s; i = pre[i])
{
mp[pre[i]][i] -= mi;//相应的边的权值都减去最小权值
mp[i][pre[i]] += mi;//反向边则加上
}
ans += mi;//结果加上这个最小权值
}
return ans;
}
int main()
{
long long i,aa,bb,cc;
while(scanf("%lld %lld",&m, &n)!=EOF)//边的数目,点的数目(1~n)
{
memset(mp,0,sizeof(mp));
for(i = 0; i < m; i ++)
{
scanf("%lld %lld %lld",&aa, &bb,&cc);
mp[aa][bb] +=cc;
}
printf("%lld\n",EK(1,n));//从1到n的最大流
}
}