題目大意:
有一個農田,爲了排水,約翰挖了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;
}