网络流初步之最大流(增广路算法)

网络流是一个联通图;

网络流有如下三个性质:

1.一条边上容量恒大于流量,即c(i,j)>=f(i,j)

2.斜对称性,f(u,v)=-f(v,u);

3.对于非源点和汇点有{f(i,j)}{i,j属于E}=0;

为了更方便算法的实现,一般根据原网络定义一个残量网络。其中r(u,v)为残量网络的容量。
r(u,v) = c(u,v) – f(u,v)

*反向边也有r!!!!

增广路是指一条源点到汇点的链,链上满足r(u,v)>0就可以对其进行增广!

可以用dfs 或bfs实现

#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstring>
#define MAXX 1100
#define INF 1000000000
using namespace std;
struct node{
  int to,c,re;
};
vector<node>edge[MAXX*4];
bool vis[MAXX];
int n,m,x,y,z;
void add(int from,int to,int ww){
  edge[from].push_back((node){to,ww,edge[to].size()});
  edge[to].push_back((node){from,0,edge[from].size()-1});
}
int dfs(int s,int t,int T){
  if(s==t)return T;
  vis[s]=true;
  for(int i=0;i<edge[s].size();++i){
    node &tp=edge[s][i];
    if(vis[tp.to]==false&&tp.c>0){
      int dd=dfs(tp.to,t,min(T,tp.c));
      if(dd>0){
	tp.c-=dd;
	edge[tp.to][tp.re].c+=dd;
	return dd;
      }
    }
  }
  return 0;
}
int maxflow(int s,int t){
  int flow=0;
  while(1){
    memset(vis,false,sizeof(vis));
    int f=dfs(s,t,INF);
    if(f==0)return flow;
    flow+=f;
  }
}
int main(){
  while(scanf("%d%d",&n,&m)!=EOF){
    memset(edge,0,sizeof(edge));
   for(int i=1;i<=n;++i){
     scanf("%d%d%d",&x,&y,&z);
     add(x,y,z);
   }
   printf("%d
",maxflow(1,m));
  }
  return 0;
}


原文地址:https://www.cnblogs.com/zzmmm/p/6501172.html