题目大意:
有一个农田,为了排水,约翰挖了m条排水沟联通各个节点,问最大水流量是多少。
算法分析:
我之前做一道要用到最大流,于是我去学习最大流算法的解法,看了n篇博客,最后还是看得一知半解,结果最后还是硬生生将模板背了下来,但是不知道为什么要这样做,以后有空再研究研究。
最大流问题的关键是寻找增广路,E-K算法是用队列的方式是查询增广路,然后去增广路上的最小流量,然后每条路径都加上最小流量,对称路径减去最小流量。我花了一些时间,终于将这道题A出来了,最关键的是,这道题会有重边,而且你还不能取最大值,而是累加重边的权值(真是日了狗)。
代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
int from;
int to;
int flow;
int cap;
bool in;
} edge[220][220];
int m, n;
int add[220];
int pre[220];
int Q[220];
bool statu[220]; // 标记当前结点是否已经进入队列
int main()
{
int x, y, z;
while (scanf("%d%d", &m, &n) != EOF) {
int maxn = 0;
memset(edge, 0, sizeof(edge));
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &x, &y, &z);
edge[x][y].cap += z;
edge[x][y].in = edge[y][x].in = true;
}
bool flag = true;
while (flag) {
int front_, rear_;
front_ = rear_ = 1;
flag = false;
memset(statu, 0, sizeof(statu));
pre[1] = 0;
Q[1] = 1;
add[1] = 1 << 30;
while (front_ <= rear_ && !flag) {
int index = Q[front_++]; // 取出队首元素
for (int i = 1; i <= n; i++) {
if (edge[index][i].in && !statu[i] && edge[index][i].cap > edge[index][i].flow && i != pre[index]) {
add[i] = min(add[index], edge[index][i].cap-edge[index][i].flow);
statu[i] = true;
pre[i] = index;
Q[++rear_] = i; // 入队列
if (i == n) {
flag = true;
break;
}
}
}
}
if (!flag) {
break; // 防止反复加
}
for (int i = n; i != 1; i = pre[i]) {
edge[pre[i]][i].flow += add[n];
edge[i][pre[i]].flow -= add[n];
}
maxn += add[n];
}
printf("%d\n", maxn);
}
return 0;
}