“ Ctrl AC!一起 AC!”
前置文章:Ford-Fulkerson
步骤:
1. 建图(残存网络,双向建图)
2. DFS:遍历图,如果流量大于零或者遇到终点即可返回F,在DFS中更新残存网络
3. 不断DFS,累加F,直到F等于零
代码:
//用于表示边的结构体(终点,容量,反向边)
struct edge { int to, cap, rev };
vector<edge> G[MAX_V]; //图的邻接表表示
bool used[MAX_V]; //DFS中用到的访问标记
//向图中增加一条从from到to的容量为cap的边,同时建立反向边,方便残存网络的更新
void add_edge(int from, int to, int cap) {
G[from].push_back((edge){ to,cap,G[to].size() });
//这里的rev指的是反向边的起点在to的所有边中的下标,因为G[to]还没新建边,所以是G[to].size()
G[to].push_back((edge){ from,0,G[from].size() - 1 });
//对于to,反向边的下标就是size-1,因为from已经建好了新边
}
//通过DFS寻找增广路
int dfs(int v, int t, int f) { //f表示当前能流的流量
if (v == t) return f; //到终点了,说明这f流量能流
used[v] = true;
for (int i = 0; i < G[v].size(); i++) {
edge& e = G[v][i];
if (!used[e.to] && e.cap > 0) {
int d = dfs(e.to, t, min(f, e.cap));
if (d > 0) {
e.cap -= d; //残存图更新
G[e.to][e.rev] += d;
return d; //dfs后返回的d>0,说明d是某条路的合法能流的,那就先流掉
}
}
}
return 0; //这条路不能流了
}
//算法总接口
int max_flow(int s, int t) {
int flow = 0;
for (;;) {
memset(used, 0, sizeof(used));
int f = dfs(s, t, INF); //开始放无限大的流量,然后再卡min
if (f == 0) return flow; //全没得流了,才会返回零,结束
flow += f; //能流的f要累加上
}
}
结合例题:【模板】网络最大流 - 洛谷
代码:
代码速记:
1.双向建图
2.max_flow():
每次dfs前先bfs:
bfs将图分层
dfs:只能走下一层,不断更新残存网络,dep为零时
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF = 0x3f3f3f3f;
struct edge {
int to, cap, rev;
};
vector<edge> G[205];
int dep[205];
int n, m, s, t;
void add_edge(int from, int to, int cap) {
edge a = { to,cap,G[to].size() };
G[from].push_back(a);
edge b = { from,0,G[from].size() - 1 };
G[to].push_back(b);
}
bool bfs() { //将图分层,并判断能否到达终点
memset(dep, 0, sizeof dep); //每次都要初始化
queue<int> q; q.push(s);
dep[s] = 1;
while (q.size()) {
int u = q.front(); q.pop();
for (int i = 0; i < G[u].size(); i++) {
edge& e = G[u][i];
if (e.cap && !dep[e.to]) {
dep[e.to] = dep[u] + 1;
q.push(e.to);
}
}
}
return dep[t];
}
int dfs(int v, int t, int f) {
if (v == t) return f;
for (int i = 0; i < G[v].size(); i++) {
edge& e = G[v][i];
if (e.cap && dep[e.to]==dep[v]+1) { //只能走下一层
int d = dfs(e.to, t, min(f, e.cap));
if (d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
dep[v] = 0; //这条路不能走了直接封锁点v,节约时间
return 0;
}
int max_flow(int s, int t) {
int flow = 0;
while (bfs()) {
flow += dfs(s, t, INF);
}
return flow;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m >> s >> t;
for (int i = 0; i < m; i++) {
int u, v, w; cin >> u >> v >> w;
add_edge(u, v, w);
}
cout << max_flow(s, t) << endl;
return 0;
}
感谢阅读!!!
“ Ctlr AC!一起 AC!”