タイトル説明
その場合、ネットワーク図を与え、ソース及びシンクは、ネットワークは、その最大流量を求めます。
入力形式
最初の行は、4つの正の整数であり、それぞれN、M、S、T、点の数が含まれ、エッジの数、数のソース、シンクポイント数が存在します。
次のMラインはUIは、VI、wiは、VI、WIの右側に到達するエッジからI UI物品が表す3つの正の整数を含む(即ち、最大流量のWi側)
出力フォーマット
ラインは、正の整数を含むネットワークの最大フローです。
エントリー
4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40
輸出
50
説明/ヒント
時間の制約:1000ミリ秒、128M
データスケール:
N <= 10、M <= 25:データの30%を
N <= 200、M <= 1000:データの70%を
データの100%まで:N <= 10000、M <= 100000
サンプルの説明:
3つのパスのタイトルがあります。
4-> 2-> 3、ライン20を通って流れることができます
4-> 3、流れ20は、によって調製することができます
4-> 2-> 1-> 3(流れ20を費やしてきた前縁4-> 2)、流れ10によって調製することができます
したがって、20 + 20 + 10 = 50の総流量。出力50。
問題の解決策
- ネットワークフロー最大流量テンプレートのタイトル
AC-コード
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 7;
int n, m;
struct Edge {
int to;
int next;
int val;
}edge[maxn << 1]; // 双向边,开 2 倍数组
int head[maxn];
int cnt; // 边的数量,从 0 开始编号
int depth[maxn]; // 分层图标记深度
int cur[maxn]; // 当前弧优化,记录当前点 u 循环到了哪一条边
void add(int u, int v, int w) {
edge[cnt].to = v;
edge[cnt].next = head[u];
edge[cnt].val = w;
head[u] = cnt++;
}
// bfs分层图
bool bfs(int s, int t) {
queue<int>q;
memset(depth, 0, sizeof depth);
depth[s] = 1; // 源点深度为 1
cur[s] = head[s];
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (edge[i].val > 0 && depth[v] == 0) { // 如果残量不为0,且 v 还未分配深度
depth[v] = depth[u] + 1;
cur[v] = head[v]; //------当前弧优化,注意在bfs里,这样做到了“按需赋值”,因为Dinic本来上界就松得一匹, BFS的过程中不连通的点根本就不用再管了...
if (v == t) // -----分层图汇点优化:遇到汇点直接返回------
return true;
q.push(v);
}
}
}
return depth[t]; // 汇点深度为 0:不存在分层图,返回false;
// 非 0 :存在增广路,返回true
}
// dfs寻找增广路
int dfs(int u, int flow, int t) {
if (u == t || flow <= 0) // 到达汇点
return flow;
int rest = flow;
for (int i = cur[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (depth[v] == depth[u] + 1 && edge[i].val != 0) { // 满足分层图、残量>0 两个条件
int k = dfs(v, min(rest, edge[i].val), t); // 向下增广
if (k < 0) // ------无用点优化-----
depth[v] = 0;
rest -= k;
edge[i].val -= k; // 正向边减
edge[i ^ 1].val += k; // 反向边加
if (rest <= 0) //------剩余量优化:在进行增广的时候,如果该节点已经没有流量,直接退出------
break;
}
}
return flow - rest; // flow:推送量,rest:淤积量,flow - rest:接受量/成功传递量
}
int Dinic(int s, int t) {
int ans = 0;
while (bfs(s, t)) {
ans += dfs(s, inf, t);
}
return ans;
}
int main() {
ios;
int s_, t_;
while (cin >> n >> m >> s_ >> t_) {
::cnt = 0;
memset(head, -1, sizeof head);
for (int i = 1, a, b, c; i <= m; i++) {
cin >> a >> b >> c;
add(a, b, c);
add(b, a, 0);
}
cout << Dinic(s_, t_) << endl;
}
}