#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define maxn 1000
#define maxe 1000000
#define INF 1000000000
struct edge{
int v,r;
int next;
}E[maxe*4];
int head[maxn+10],c;
void init(){
memset(head,-1,sizeof(head));
c=0;
}
void add_edge(int u,int v,int r){
E[c].v=v;E[c].r=r;E[c].next=head[u];
head[u]=c++;
E[c].v=u;E[c].r=0;E[c].next=head[v];
head[v]=c++;
}
int n,m;
int s,t;
queue<int>Q;
int d[maxn+10];
int flow[maxn+10];
int dfs(int u){
if(u==t)return INF;
for(int i=head[u];i!=-1;i=E[i].next){
int v=E[i].v;int r=E[i].r;
if(r>0&&d[v]==d[u]+1){
flow[v]=min(flow[u],E[i].r);
int f=dfs(v);
if(!f)continue;
f=min(f,flow[v]);
E[i].r-=f;
E[i^1].r+=f;
return f;
}
}
return 0;
}
bool bfs(){
memset(d,0,sizeof(d));
d[s]=1;
Q.push(s);
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=head[u];i!=-1;i=E[i].next){
int v=E[i].v,r=E[i].r;
if(r>0&&!d[v]){
d[v]=d[u]+1;
Q.push(v);
}
}
}
return d[t];
}
int dinic(int s,int t){
int f=0;flow[s]=INF;
while(bfs())f+=dfs(s);
return f;
}
int main(){
freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
init();
for(int i=0;i<m;i++){
int u,v,r;
scanf("%d%d%d",&u,&v,&r);
add_edge(u,v,r);
}
scanf("%d%d",&s,&t);
printf("%d\n",dinic(s,t));
return 0;
}
基本思路:找增广路,沿增广路增广,最终得到最大流。每次寻找增广路之前,先给图中每个结点标记一个高度值d。增广路可以是一条结点高度递增的简单路径。这样DFS增广路时,就不会走很多冤枉路。
假设当前访问到了u的子节点v,有d[v]=d[u]+1,那么这条增广路的流量是min(从源点到u点的容量,边(u,v)的残存容量,v到汇点t的容量)。所以需要一个flow[]来记录源点到每个结点的容量。
细节:由于使用前向星存边,先读入的边后处理。
下面是一组数据的运行示意,在文章的最后,给出了本组样例的输入,以方便您进行测试。
6 10
1 2 16
1 3 13
2 3 10
2 4 12
3 2 4
3 5 14
4 3 9
4 6 20
5 4 7
5 6 4
1 6