在这里插入代码片
输入
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
输出
50
`
网络最大流
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
#define inf 0x7fffffff
struct Edge
{
int v,w,nxt;
} g[100001<<2];
int head[100001<<2];
int cnt;
void addEdge(int u,int v,int w)
{
g[cnt].v = v;
g[cnt].w = w;
g[cnt].nxt = head[u];
head[u] = cnt;
++ cnt;
}
int n,m,x,y,z;
int ans,flow;
int dis[100001];
queue<int> q;
int S,T;
void init()
{
memset(head,-1,sizeof(head));
memset(g,0,sizeof(g));
cnt = 0;
memset(dis,-1,sizeof(dis));
while(!q.empty()) q.pop();
ans = 0;
}
int bfs()
{
memset(dis,-1,sizeof(dis));
while(!q.empty()) q.pop();//清空队列元素
dis[S] = 0;
q.push(S);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i=head[u]; i!=-1; i=g[i].nxt)
{
int v = g[i].v;
if(dis[v]==-1 && g[i].w > 0)//流量大于0既可以继续流
{
dis[v] = dis[u] + 1;分层
q.push(v);
}
}
}
return dis[T]!=-1;
}
int dfs(int u,int exp)
{
if(u==T) return exp;
int flow=0,tmp= 0;
for(int i=head[u]; i!=-1; i=g[i].nxt)
{
int v = g[i].v;
if((dis[v] == (dis[u]+1)) && (g[i].w>0))
{
tmp = dfs(v,min(exp,g[i].w));//exp存增光路最小的流量
if(!tmp) continue;//tep为0找不到增广路
exp -= tmp;
flow += tmp;
g[i].w -= tmp;
g[i^1].w += tmp;//使用的是向前星,每一次建边都是相邻的,奇数为正边偶数为负边,所以异或之后就是反边
if(!exp) break;
}
}
return flow;
}
int main()
{
scanf("%d %d %d %d",&n,&m,&S,&T);
init();
for(int i=1; i<=m; ++i)
{
scanf("%d%d%d",&x,&y,&z);
addEdge(x,y,z);
addEdge(y,x,0);
}
while(bfs())
{
ans += dfs(S,inf);//一次bfs找完之后再继续寻找,看是否可以继续分层。
}
printf("%d\n",ans);
}