题意
给你一个网络图,以及源点和汇点,求最大流
题解(EK)
先读入一个有向图,记录源点到每个节点的流量,每个节点的前驱
从汇点倒着用bfs寻找增广路径(1次只找一条),最后算出最大流
话说从源点开始,记录后继也可以
调试记录
读入顺序
因为是单向图,所以判断now和i之间有连接时,只能取e[now][i]
#include <cstdio>
#include <queue>
#define maxn 2005
#define INF 0x3f3f3f3f
using namespace std;
int n, m, S, T, maxflow = 0;
int e[maxn][maxn], flow[maxn], pre[maxn];
int bfs(int s, int t){
queue <int> q;
for (int i = 1; i <= n; i++) pre[i] = -1;
pre[s] = 0;
q.push(s); flow[s] = INF;
while (!q.empty()){
int now = q.front(); q.pop();
for (int i = 1; i <= n; i++)
if (e[now][i] && pre[i] == -1){
pre[i] = now;
q.push(i);
flow[i] = min(flow[now], e[now][i]);
}
}
if (pre[t] == -1) return -1;
else return flow[t];
}
void EK(int s, int t){
int inc = 0;
while ((inc = bfs(s, t)) != -1){
int k = t;
while (k != s){
int last = pre[k];
e[last][k] -= inc;
e[k][last] += inc;
k = last;
}
maxflow += inc;
}
}
int main(){
scanf("%d%d%d%d", &n, &m, &S, &T);
for (int x, y, z, i = 1; i <= m; i++){
scanf("%d%d%d", &x, &y, &z);
e[x][y] += z;
}
EK(S, T);
printf("%d\n", maxflow);
return 0;
}
题解(Dinic)
EK的优化,用bfs预处理分层,用dfs找增广路径
调试记录
开始cnt必须=-1,因为cnt ^ 1即为cnt的反向边
若cnt=0,1^1\(\not\) = 2
#include <cstdio>
#include <queue>
#include <cstring>
#define maxn 1000005
#define INF 0x3f3f3f3f
using namespace std;
struct node{
int to, next, dis;
}e[maxn];
int n, m, s, t, maxflow = 0, cnt = -1;
int deep[maxn], head[maxn];
void AddEdge(int u, int v, int len){
e[++cnt] = (node){v, head[u], len};
head[u] = cnt;
}
bool bfs(){
queue <int> q; while (!q.empty()) q.pop();
memset(deep, 0, sizeof deep);
deep[s] = 1; q.push(s);
while (!q.empty()){
int now = q.front(); q.pop();
for (int i = head[now]; i != -1; i = e[i].next){
if (!deep[e[i].to] && e[i].dis){
deep[e[i].to] = deep[now] + 1;
q.push(e[i].to);
}
}
}
return (deep[t] != 0);
}
int dfs(int cur, int ans){
if (cur == t) return ans;
int flow;
for (int i = head[cur]; i != -1; i = e[i].next){
if (deep[e[i].to] == deep[cur] + 1 && e[i].dis){
if (flow = dfs(e[i].to, min(ans, e[i].dis))){
e[i].dis -= flow;
e[i ^ 1].dis += flow;
return flow;
}
}
}
return 0;
}
void Dinic(){
while (bfs()){
while (int tmp = dfs(s, INF))
maxflow += tmp;
}
}
int main(){
memset(head, -1, sizeof head);
scanf("%d%d%d%d", &n, &m, &s, &t);
for (int x, y, z, i = 1; i <= m; i++){
scanf("%d%d%d", &x, &y, &z);
AddEdge(x, y, z); AddEdge(y, x, 0);
}
Dinic();
printf("%d\n", maxflow);
return 0;
}