学习网络流的第一个题目,强烈推荐。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
int n;
int m;
#define E 400500
#define V 400500
#define inf 10050000
struct Edge{
int u,v,c,next;
}edge[E];
int cnt;
int dist[V];
int head[V];
int que[V];
int sta[V];
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c){
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c;
edge[cnt].next=head[u];head[u]=cnt++;
edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=0;
edge[cnt].next=head[v];head[v]=cnt++;
}
int dinic(int s,int t){
int ans=0;
while(true){
int left,right,u,v;
memset(dist,-1,sizeof(dist));
left=right=0;
que[right++]=s;
dist[s]=0;
while(left<right){
u=que[left++];
for(int k=head[u];k!=-1;k=edge[k].next){
u=edge[k].u;
v=edge[k].v;
if(edge[k].c>0 && dist[v]==-1){
dist[v]=dist[u]+1;
que[right++]=v;
if(v==t){
left=right;
break;
}
}
}
}
if(dist[t]==-1) break;
int top=0;
int now=s;
while(true){
if(now!=t){
int k;
for(k=head[now];k!=-1;k=edge[k].next){
if(edge[k].c>0 && dist[edge[k].v]==dist[edge[k].u]+1) break;//这条边在上面找到的增广路上
}
if(k!=-1){
sta[top++]=k;
now=edge[k].v;
}
else{
if(top==0) break;//当且仅当栈空时退出
dist[edge[sta[--top]].v]=-1;//退回来重新找
now=edge[sta[top]].u;
}
}
else{
int flow=inf,ebreak;
for(int i=0;i<top;i++){
if(flow>edge[sta[i]].c){
flow=edge[sta[i]].c;
ebreak=i;//找到增广路上剩余流量最小的边,记录下来。
}
}
ans+=flow;
for(int i=0;i<top;i++){
edge[sta[i]].c-=flow;//顺向边减去剩余流量最小的边
edge[sta[i]^1].c+=flow;//逆向边加上剩余流量最小的边
}
now=edge[sta[ebreak]].u;
top=ebreak;
}
}
}
return ans;
}
int main()
{
int a,b,c;
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&m,&n)!=EOF){
init();
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
}
printf("%d\n",dinic(1,n));
}
return 0;
}