目录
学习了Dinic算法,尝试通过算法思想使用C++实现了一下。
程序思想
- 1)初始化程序,设置容量网络和网络流
- 2)DFS()构造残留网络、BFS()构造层次网络,层次网络中找不到汇点便结束算法
- 3)在层次网络中不断进行增广,知道层次网络中没有增广路;每次增广都要去掉已饱和的弧
- 4)转到步骤2)
提示
程序中Dinic()循坏调用BFS()不断构建层次网络,每次构建好调用则循环DFS()增广,因此步骤2,3的一次循环便是一个阶段,每个阶段中都是根据残留网络建立层次网络然后进行增广,直到找不到增广路为止。在程序实现的时候,并不需要真正“构造”层次网络,只需要对每个顶点标记层次,增广的时候,判断边是否满足layer(v) = layer(u)+1这一约束条件即可。
C++代码
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
//邻接矩阵存储图 储存容量和流量
struct Vertex
{
int c;
int f;
}G[100][100];
int Edge, Vex; // 边数 节点数
int layer[100]; //层数数组
int v_s, v_e, v_c; // 每条边起点、终点和流量
const int INF = 0x7fffffff;
bool BFS(); // 广度优先BFS构造层次网络
int DFS(int u, int cp); // 深度优先DFS找寻增广路
int Dinic(); // Dinic算法
int Dinic() {
int sum=0, tf=0;
while (BFS()) {
while (tf = DFS(1, INF))
sum += tf;
}
return sum;
}
bool BFS()
{
queue<int> q;
memset(layer, 0, sizeof(layer));
q.push(1);
layer[1] = 1;
int u, v;
while (!q.empty()) {
u = q.front();
q.pop();
for (v = 1; v <= Vex; v++) {
if (!layer[v] && G[u][v].c>G[u][v].f) {
layer[v] = layer[u] + 1;
q.push(v);
}
}
}
return layer[Vex] != 0;
}
int DFS(int u, int cp) {
int tmp = cp;
int v, t;
if (u == Vex)
return cp;
for (v = 1; v <= Vex&&tmp; v++) {
if (layer[u] + 1 == layer[v]) {
if (G[u][v].c>G[u][v].f) {
t = DFS(v, min(tmp, G[u][v].c - G[u][v].f));
G[u][v].f += t;
G[v][u].f -= t;
tmp -= t;
}
}
}
return cp - tmp;
}
int main() {
printf("请输入边数和节点数(空格隔开):\n");
while (scanf("%d%d", &Edge, &Vex)) {
memset(G, 0, sizeof(G));
if(Edge!=0) printf("请输入每条边起点 终点 权值:\n") ;
while (Edge--) {
scanf("%d%d%d", &v_s, &v_e, &v_c);
G[v_s][v_e].c += v_c;
}
int max_c = Dinic();
printf("\n汇点最大流量为:%d", max_c);
}
return 0;
}