1、dinic(递归)
/*
接口
int maxflow();
复杂度:上界为O(N2M),一般效率很高
输入:src,sink 表示源点和汇点
g,c 全局变量,表示存边的邻接表
输出:最大流
*/
//#pragma comment(linker, "/STACK:1024000000,1024000000") //用C++提交可以防栈溢出
#include <iostream>
#include <queue>
#include <climits>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 20000,maxm = 500000; //最大的点数和边数
struct Edge{
int v,f,nxt;
};
int src,sink;
int g[maxn + 10];
int nume;
Edge e[maxm*2+10];
void addedge(int u,int v,int c){ //加边操作,表示加一条u到v容量为c的边。请务必在开始加边之前把nume赋值成1,并把g数组赋值为0。
e[++nume].v = v;
e[nume].f = c;
e[nume].nxt = g[u];
g[u] = nume;
e[++nume].v = u;
e[nume].f=0;
e[nume].nxt = g[v];
g[v] = nume;
}
void init(){
memset(g,0,sizeof(g));
nume=1;
//加边
}
queue<int> que;
bool vis[maxn+10];
int dist[maxn+10];
void bfs(){
memset(dist,0,sizeof(dist));
while(!que.empty())
que.pop();
vis[src]=true;
que.push(src);
while(!que.empty()){
int u = que.front();
que.pop();
for(int i=g[u]; i; i=e[i].nxt) {
if(e[i].f && !vis[e[i].v]){
que.push(e[i].v);
dist[e[i].v]=dist[u]+1;
vis[e[i].v]=true;
}
}
}
}
int dfs(int u,int delta){
if(u==sink){
return delta;
}else{
int ret=0;
for(int i=g[u];delta && i;i=e[i].nxt){
if(e[i].f && dist[e[i].v]==dist[u]+1){
int dd=dfs(e[i].v,min(e[i].f,delta));
e[i].f-=dd;
e[i^1].f+=dd;
delta-=dd;
ret+=dd;
}
}
//if(!ret) dist[u]=-2; //优化
return ret;
}
}
int maxflow(){
int ret=0;
while(true){
memset(vis,0,sizeof(vis));
bfs();
if(!vis[sink])
return ret;
ret+=dfs(src,INT_MAX);
}
}
int main (){
init();
src=1,sink=4;
addedge(1,2,20);
addedge(1,3,10);
addedge(2,3,5);
addedge(2,4,10);
addedge(3,4,20);
cout << maxflow() << endl;
return 0;
}
2、dinic(非递归)
#include <cstdio>
#include <cstring>
#include <iostream>
#include <climits>
using namespace std;
const int maxn = 100000+10;
const int maxm = 200000+10;//双向边需要加倍
int nume,dist[maxn],que[maxn],g[maxn];
struct ede{
int u,v,f,next;
} e[maxm];
void addedge(int u,int v,int f){
e[nume].u=u;
e[nume].v=v;
e[nume].next=g[u];
e[nume].f=f;
g[u]=nume++;
e[nume].u=v;
e[nume].v=u;
e[nume].next=g[v];
e[nume].f=0;
g[v]=nume++;
}
int dinic(int s,int t)
{
int ans=0;
while(true){
int head,tail,id,i;
head=tail=0;
que[tail++]=s;
memset(dist,-1,sizeof(dist));
dist[s]=0;
while(head<tail){
id=g[que[head++]];
while(id!=-1){
if(e[id].f>0&&dist[e[id].v]==-1){
dist[e[id].v]=dist[e[id].u]+1;
que[tail++]=e[id].v;
if(e[id].v==t){
head=tail;
break;
}
}
id=e[id].next;
}
}
if(dist[t]==-1)
break;
id=s,tail=0;
while(true){
if(id==t){
int flow=INT_MAX,fir;
for(i=0; i<tail; i++)
if(e[que[i]].f<flow){
fir=i;
flow=e[que[i]].f;
}
for(i=0; i<tail; i++)
e[que[i]].f-=flow,e[que[i]^1].f+=flow;
ans+=flow;
tail=fir;
id=e[que[fir]].u;
}
id=g[id];
while(id!=-1){
if(e[id].f>0&&dist[e[id].u]+1==dist[e[id].v])
break;
id=e[id].next;
}
if(id!=-1){
que[tail++]=id;
id=e[id].v;
}
else{
if(tail==0)
break;
dist[e[que[tail-1]].v]=-1;
id=e[que[--tail]].u;
}
}
}
return ans;
}
void init(){
nume=0;
memset(g,-1,sizeof(g));
}
int main(){
int src,sink;//源点,汇点
init();//初始化
int u,v,c;
addedge(u,v,c);//加边
dinic(src,sink);//最大流
return 0;
}