P3376 【模板】网络最大流 dinic详解
dinic的核心在于分层和多路增广。
分层的意思是,对于图用bfs搜出每一层,避免出现dfs深度过深的情况。
多路增广,利用的是dfs的回溯性质,这样就可以在一个点增广出它的所有流量。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int maxn=200100;
const int INF=0x3f3f3f3f;
int head[maxn];
int val[maxn];
int next[maxn];
int to[maxn];
int deep[maxn];
int cnt=1,n,m,s,t;
void addEdge(int u,int v,int w)
{
to[++cnt]=v;
val[cnt]=w;
next[cnt]=head[u];
head[u]=cnt;
}
bool bfs()
{
memset(deep,0,sizeof(deep));
deep[s]=1;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u=q.front();
q.pop();
for (int i=head[u];i;i=next[i]) {
int v=to[i];
if (!deep[v]&&val[i]) {
deep[v]=deep[u]+1;
q.push(v);
}
}
}
return deep[t];
}
int dfs(int u,int in)
{
if (u==t) {
return in;
}
int out=0;
for (int i=head[u];i&∈i=next[i]) {
int v=to[i];
if (val[i]&&deep[v]==deep[u]+1) {
int res=dfs(v,min(val[i],in));
val[i]-=res;
val[i^1]+=res;
in-=res;
out+=res;
}
}
if (out==0) {
deep[u]=0;
}
return out;
}
int dinic()
{
int ans=0;
while (bfs()) {
ans+=dfs(s,INF);
}
return ans;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
while (m--) {
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
addEdge(v,u,0);
}
printf("%d\n",dinic());
return 0;
}