这两天学习了网络流有关的部分, 了解了 3个 求最大流的 算法( EK, FF, Dinic )
比较重要的概念有: 增广矩阵、增广路、反向边
EK算法用的是BFS
FF算法用的是DFS
Dinic 算法结合了上述两个算法的优点: 先用BFS将图划分层次, 然后在用DFS找源点到汇点的增广路径
用一道网络流入门题练练手 (poj 1273),代码如下:
//poj 1273 基础最大流问题
// EK 算法
#include <iostream>
#include <queue>
using namespace std;
#define inf 1 << 30
#define maxn 201
int v_num, e_num;
int cap[maxn][maxn];
int flow[maxn];
int pre[maxn];
int bfs() {
queue<int> q;
memset(flow, 0, sizeof(flow));
memset(pre, -1, sizeof(pre));
flow[1] = inf;
q.push(1);
while (!q.empty()) {
int t = q.front();
q.pop();
if (t == v_num)
break;
for (int i = 2; i <= v_num; i++) {
if (pre[i] == -1 && cap[t][i] > 0) {
pre[i] = t;
flow[i] = min(flow[t], cap[t][i]);
q.push(i);
}
}
}
return flow[v_num];
}
void EK_maxFlow() {
int d;
int maxflow = 0;
while (d = bfs()) {
int k = v_num;
int last;
while (k != 1) {
last = pre[k];
cap[last][k] -= d;
cap[k][last] += d;
k = last;
}
maxflow += d;
}
printf("%d\n", maxflow);
}
int main() {
int from, to, c;
while (~scanf("%d%d", &e_num, &v_num)) {
memset(cap, 0, sizeof(cap));
for (int i = 0; i < e_num; i++) {
scanf("%d%d%d", &from, &to, &c);
cap[from][to] += c;
}
EK_maxFlow();
}
//system("pause");
return 0;
}
// poj 1273 ford-fulkson 算法
#include <iostream>
#include <algorithm>
using namespace std;
#define inf 1 << 30
#define maxn 201
int cap[maxn][maxn];
int used[maxn];
int v_num, e_num;
int dfs(int s, int d, int f) {
if (s == d) return f;
for (int i = 1; i <= v_num; i++) {
if (!used[i] && cap[s][i] > 0) {
used[i] = 1;
int delta = dfs(i, d, min(f, cap[s][i]));
if (delta > 0) {
cap[s][i] -= delta;
cap[i][s] += delta;
return delta;
}
}
}
return 0;
}
int maxflow(int src, int des) {
int f = 0, d = 0;
while (true) {
memset(used, 0, sizeof(used));
used[1] = 1;
if (!(d = dfs(src, des, inf))) return f;
f += d;
}
}
int main() {
int from, to, len;
while (~scanf("%d%d", &e_num, &v_num)) {
memset(cap, 0, sizeof(cap));
for (int i = 0; i < e_num; i++) {
scanf("%d%d%d", &from, &to, &len);
cap[from][to] += len;
}
printf("%d\n", maxflow(1, v_num));
}
//system("pause");
return 0;
}
// poj 1273 Dinic 算法
#include <iostream>
#include <queue>
using namespace std;
#define inf 1 << 30
#define maxn 201
int v_num, e_num;
int cap[maxn][maxn];
int deg[maxn];
bool vis[maxn];
int BFS(int src, int des) {
memset(deg, -1, sizeof(deg));
queue<int> q;
vis[src] = true, deg[src] = 0;
q.push(src);
while (!q.empty()) {
int t = q.front();
q.pop();
if (t == des) break;
for (int i = 1; i <= v_num; i++) {
if (deg[i] == -1 && cap[t][i] > 0) {
deg[i] = deg[t] + 1;
q.push(i);
}
}
}
return deg[des] != -1;
}
int DFS(int src, int des, int f) {
if (src == des) return f;
for (int i = 1; i <= v_num; i++) {
if (!vis[i] && deg[i] - deg[src] == 1 && cap[src][i] > 0) {
vis[i] = true;
int delta = DFS(i, des, min(f, cap[src][i]));
if (delta > 0) {
cap[src][i] -= delta;
cap[i][src] += delta;
return delta;
}
}
}
return 0;
}
int Dinic(int src, int des) {
int f = 0, delta = 0;
while (BFS(src, des)) {
while (true) {
memset(vis, false, sizeof(vis));
delta = DFS(src, des, inf);
if (delta == 0) break;
f += delta;
}
}
return f;
}
int main() {
int from, to, len;
while (~scanf("%d%d", &e_num, &v_num)) {
memset(cap, 0, sizeof(cap));
for (int i = 0; i < e_num; i++) {
scanf("%d%d%d", &from, &to, &len);
cap[from][to] += len;
}
printf("%d\n", Dinic(1, v_num));
}
//system("pause");
return 0;
}