https://www.cnblogs.com/LUO77/p/6115057.html
https://www.cnblogs.com/linzhengmin/p/9313216.html
https://blog.youkuaiyun.com/pi9nc/article/details/11860409
Dinic算法
1、矩阵版模板(适用于顶点少的情况)
#include<queue>
#include<cstdio>
#include<cstdio>
#include<cstring>
#define INF 0x3f3f3f3f
#define N 1001
using namespace std;
int E, V;//V个点E条边
int S,T;//源点、汇点
int level[N];//存储结点分层层数
struct Edge
{
int cap;
int flow;
} edge[N][N];
bool bfs() //构造层次网络
{
memset(level,0,sizeof(level));/***初始化 为 层次0***/
queue<int> Q;
Q.push(S);
level[S]=1;/**源点S 的 层次 为 1**/
while(!Q.empty())
{
int x=Q.front();
Q.pop();
for(int y=1; y<=n; y++)
{
if(!level[y]&&edge[x][y].cap>edge[x][y].flow)/****y点还未在构次网络中**并且*如果剩余流量大于 0 , 就将其构造进层次网络****/
{
level[y]=level[x]+1;/***y 的层次 是他 x +1***/
Q.push(y);
}
}
}
return level[T]!=0;/******T节点为 0 表示 没有 构造出 到 T(汇点)的 层次网络****/
}
/********************
在 层次网络上寻找增广路,计算可增加流量,↓↓
****************/
int dfs(int x,int cp)/****** cp 表示上一次的最小流量, 第一次cp 初始化为 INF ***/
{
if(x==n)/********递归边界*****/
return cp;
int flow=cp;//记录从x到t的最小残量
for(int y=1; y<=n; y++)
{
if(level[x]+1==level[y])/****寻找下一层*****/
{
if(edge[x][y].cap>edge[x][y].flow)
{
int minn=min(flow,edge[x][y].cap-edge[x][y].flow);/********增量 取决与该增广路最小的流量*********/
int newFlow=dfs(y,minn);/*******************************/
edge[x][y].flow+=newFlow;
edge[y][x].flow-=newFlow;
flow-=newFlow;
}
}
}
return cp-flow;/*****cp - flow 是增加量********/
}
int dinic()
{
int flow=0;
int tf=0;/***增量***/
while(bfs())/****能构 层次网络 一定存在增广路***/
{
while(tf=dfs(1,INF))/****知道增量 为 0 表示 该层次网络没有曾广路了****/
{
flow+=tf;
}
}
return flow;
}
int main()
{
scanf("%d%d",&E,&V);
memset(edge,0,sizeof(edge));
while(E--)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
edge[x][y].cap+=w;//便于处理重边
}
S=1,T=V;
printf("%d\n",dinic());
return 0;
}
2、邻接表版(适用于顶点多的情况)
- vector+ 边集数组实现(邻接表)(自己写的):
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e4+5;
int V, E, S, T;
int tot;
int level[maxn];
struct Edge
{
int from, to;
int cap;
int flow;
};
vector<int>G[maxn];
vector<Edge>edge;
void init()
{
for(int i = 0;i < V;i++)
{
G[i].clear();
}
}
void input()
{
int tot = 0;
scanf("%d %d %d %d", &V, &E, &S, &T);
init();
while(E--)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
Edge temp;
temp.cap = w;
temp.flow = 0;
temp.from = u;
temp.to = v;
edge.push_back(temp);
G[u].push_back(tot++);
temp.cap = 0; temp.from = v; temp.to = u;
edge.push_back(temp);
G[v].push_back(tot++);
}
}
bool bfs()
{
memset(level , 0 , sizeof(level));
queue<int>q;
level[S] = 1;
q.push(S);
int x;
while(!q.empty())
{
x = q.front();
q.pop();
for(int i = 0;i < (int )G[x].size();i++)
{
int e = G[x][i];
int y = edge[e].to;
if(!level[y]&&edge[e].cap > edge[e].flow)
{
level[y] = level[x]+1;
q.push(y);
}
}
}
return level[T] != 0;
}
int dfs(int x, int cp)
{
if(x == T)
{
return cp;
}
int flow = cp;
for(int i = 0;i <(int)G[x].size();i++)
{
int e = G[x][i];
int y = edge[e].to;
if(level[y] == level[x]+1 && edge[e].cap >edge[e].flow)
{
int minn = min(flow, edge[e].cap - edge[e].flow);
int newflow = dfs(y, minn);
flow-=newflow;
edge[e].flow+=newflow;
edge[e^1].flow-=newflow;
}
}
return cp - flow;
}
int dinic()
{
int flow = 0;
int tf = 0;
while(bfs())
{
while(tf = dfs(S, INF))
{
flow+=tf;
}
}
return flow;
}
int main()
{
input();
int maxflow = dinic();
printf("%d", maxflow);
return 0;
}
- 数组+边集数组(邻接表)
#include<bits/stdc++.h>
using namespace std;
const int maxn2 = 1e6+50;
const int maxn = 1e5;
const int INF = 0x3f3f3f;
int V, E, S, T;
int tot;
struct Edge/***表边****/
{
int from, to;
int cap, flow;
int next;
}edge[maxn2];
int head[maxn]; /***表头**/
int level[maxn];
void init()
{
memset(edge, 0, sizeof(edge));
memset(head, -1, sizeof(head));
}
void add(int u, int v, int w)
{
edge[tot].cap = w;
edge[tot].from = u;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
edge[tot].cap = 0;
edge[tot].from = v;
edge[tot].to = u;
edge[tot].next = head[v];
head[v] = tot++;
}
void input()
{
scanf("%d %d %d %d", &V, &E, &S, &T);
tot = 0;
while(E--)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
add(u, v, w);
}
}
bool bfs()
{
memset(level, 0, sizeof(level));
queue<int>q;
level[S] = 1;
q.push(S);
int x;
while(!q.empty())
{
x = q.front();
q.pop();
for(int i = head[x];i!= -1;i = edge[i].next)
{
int y = edge[i].to;
if(!level[y]&& edge[i].cap > edge[i].flow)
{
level[y] = level[x]+1;
q.push(y);
}
}
}
return level[T]!= 0;
}
int dfs(int x, int cp)
{
if(x == T)return cp;
int flow = cp;
for(int i = head[x];i!= -1;i = edge[i].next)
{
int y = edge[i].to;
if(level[y] == level[x]+1 && edge[i].cap > edge[i].flow)
{
int minn = min(flow, edge[i].cap - edge[i].flow);
int newflow = dfs(y, minn);
flow-= newflow;
edge[i].flow+=newflow;
edge[i^1].flow-=newflow;
}
}
return cp - flow;
}
int dinic()
{
int flow = 0;
int tf = 0;
while(bfs())
{
while(tf = dfs(S, INF))
{
flow+=tf;
}
}
return flow;
}
int main()
{
init();
input();
int maxflow = dinic();
printf("%d", maxflow);
return 0;
}