題目鏈接:luogu P3376
題目
如題,給出一個網絡圖,以及其源點和匯點,求出其網絡最大流。
輸入
第一行包含四個正整數、、、,分別表示點的個數、有向邊的個數、源點序號、匯點序號。
接下來行每行包含三個正整數、、,表示第i條有向邊從出發,到達,邊權爲(即該邊最大流量爲)
輸出
一行,包含一個正整數,即爲該網絡的最大流。
樣例輸入
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
樣例輸出
50
樣例解釋
題目中存在條路徑:
- 路徑爲:,該路線可通過的流量
- 路徑爲:,可通過的流量
- 路徑爲:,可通過的流量(邊之前已經耗費了的流量)
故流量總計。輸出。
數據範圍
對於的數據:,
對於的數據:,
對於的數據:,
思路
這是一道非常經典的模板題,我們這裏用算法來做。
其實就是把算法的找增廣路徑和增廣分開來,並在時進行了優化。
那優化是怎麼樣的呢?
我們在找增廣路徑的時候,我們可以將記錄這個點是否被走過的數組改成。這樣我們除了表示它有沒有被走過,還可以表示由源點到這個點走了多遠。
接着,我們在增廣的時候,我們就在某一個點的時候,我們就只找這個值剛好比他大的點走。這樣,走出我們的增廣路就快了很多了。
(我這裏記錄的變量名叫)
這樣,我們就實現了優化。
代碼
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define rr register
using namespace std;
struct note {
int to, go, op, next;
}e[200001];
int n, m, s, t, le[200001], x, y, z, k, dis[10001], ans;
queue <int> q;
int read() {//快讀
int aa = 0;
char c = getchar();
while (c > '9' || c < '0') c = getchar();
while (c <= '9' && c >= '0') {
aa = aa * 10 + c - 48;
c = getchar();
}
return aa;
}
bool bfs() {
while (!q.empty()) q.pop();//清空隊列
memset(dis, 0x7f, sizeof(dis));//初始化
dis[s] = 0;//初始化
q.push(s);
while (!q.empty()) {
int now = q.front();
q.pop();
for (rr int i = le[now]; i; i = e[i].next)
if (dis[e[i].to] > dis[now] + 1 && e[i].go) {//沒到過且可以灌水
dis[e[i].to] = dis[now] + 1;
if (e[i].to == t) return 1;//到匯點了
q.push(e[i].to);
}
}
return 0;
}
int dfs(int now, int an) {
if (now == t) return an;//到匯點了
int go = 0;
for (rr int i = le[now]; i; i = e[i].next)
if (dis[e[i].to] == dis[now] + 1 && e[i].go) {
int line_go = dfs(e[i].to, min(e[i].go, an - go));//這條增廣路最多能流多少
if (!line_go) dis[e[i].to] = -1;//之前找到的不是這條路
e[i].go -= line_go;//流
e[e[i].op].go += line_go;//反向記錄
go += line_go;//總流量
if (go == an) break;//已經全部找完了
}
return go;
}
void dinic() {
while (bfs())//還有增廣路徑
ans += dfs(s, 2147483647);//dfs加最大流
}
int main() {
n = read();//讀入
m = read();
s = read();
t = read();
for (rr int i = 1; i <= m; i++) {
x = read();//讀入
y = read();
z = read();
e[++k] = (note){y, z, k + 1, le[x]}; le[x] = k;//建鄰接表(正向)
e[++k] = (note){x, 0, k - 1, le[y]}; le[y] = k;//建鄰接表(反向)
}
dinic();//dinic算法
printf("%d", ans);//輸出
return 0;
}