网络流
最近浅学了一下网络流相关问题,做了一些基础模板题,存一下板子
最大流
最大流使用的均为 ISAP
P3376 【模板】网络最大流
#include <bits/stdc++.h>
#define INF 9223372036854775807
#define int long long
using namespace std;
const int maxn = 1e7 + 10;
int n, m, s, t, cnt = 1;
int head[maxn], vis[maxn];
int dep[maxn], num[maxn], cur[maxn], p[maxn];
struct node{
int u, v, nxt, cap, flow;
}e[maxn];
inline void add(int u, int v, int w) {
e[++cnt].u = u; e[cnt].v = v;
e[cnt].cap = w; e[cnt].flow = 0;
e[cnt].nxt = head[u]; head[u] = cnt;
}
inline void bfs() {
queue<long long> q;
vis[t] = 1; dep[t] = 0;
q.push(t);
while (!q.empty()) {
int now = q.front(); q.pop();
for (int i = head[now]; i; i = e[i].nxt)
if (vis[e[i].v] == 0 && e[i].cap == 0) {
vis[e[i].v] = 1;
dep[e[i].v] = dep[now] + 1;
q.push(e[i].v);
}
}
}
inline int agument() {
int x = t, ans = INF;
while (x != s) {
ans = min(ans, e[p[x]].cap - e[p[x]].flow);
x = e[p[x]].u;
}
x = t;
while (x != s) {
e[p[x]].flow += ans;
e[p[x] ^ 1].flow -= ans;
x = e[p[x]].u;
}
return ans;
}
long long ISAP() {
long long flow = 0;
int x = s;
for (int i = 1; i <= n; i++) num[dep[i]]++;
for (int i = 1; i <= cnt; i++) cur[i] = head[i];
while (dep[s] < n) {
if (x == t) {
flow += agument();
x = s;
}
int flag = 0;
for (int i = cur[x]; i; i = e[i].nxt)
if (e[i].cap > e[i].flow && dep[x] == dep[e[i].v] + 1) {
flag = 1;
p[e[i].v] = i;
cur[x] = i;
x = e[i].v;
break;
}
if (flag == 0) {
if (--num[dep[x]] == 0) break;
int mn = n - 1;
for (int i = head[x]; i; i = e[i].nxt)
if (e[i].cap > e[i].flow) mn = min(mn, dep[e[i].v]);
dep[x] = mn + 1;
num[dep[x]]++;
cur[x] = head[x];
if (x != s) x = e[p[x]].u;
}
}
return flow;
}
signed main() {
cin >> n >> m >> s >> t;
for (int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
add(u, v, w); add(v, u, 0);
}
bfs();
long long ans = ISAP();
cout << ans << endl;
return 0;
}
P2756 飞行员配对方案问题
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 0x7fffffff
using namespace std;
const int maxn = 1e6 + 10;
int n, m, s, t, cnt = 1;
int head[maxn], vis[maxn];
int dep[maxn], num[maxn], cur[maxn], p[maxn];
struct node{
int u, v, nxt, cap, flow;
}e[maxn];
inline void add(int u, int v, int w) {
e[++cnt].u = u; e[cnt].v = v;
e[cnt].cap = w; e[cnt].flow = 0;
e[cnt].nxt = head[u]; head[u] = cnt;
}
inline void bfs() {
/*queue<int> q;
vis[t] = 1; dep[t] = 0;
q.push(t);
while (!q.empty()) {
int now = q.front(); q.pop();
for (int i = head[now]; i; i = e[i].nxt)
if (vis[e[i].v] == 0 && e[i].cap == 0) {
vis[e[i].v] = 1;
dep[e[i].v] = dep[now] + 1;
q.push(e[i].v);
}
}*/
queue<int> q;
memset(dep, -1, sizeof(dep));
dep[t] = 0;
q.push(t);
while (!q.empty()) {
int now = q.front(); q.pop();
for (int i = head[now]; i; i = e[i].nxt)
if (dep[e[i].v] == -1) {
dep[e[i].v] = dep[now] + 1;
q.push(e[i].v);
}
}
}
inline int agument() {
int x = t, ans = INF;
while (x != s) {
ans = min(ans, e[p[x]].cap - e[p[x]].flow);
x = e[p[x]].u;
}
x = t;
while (x != s) {
e[p[x]].flow += ans;
e[p[x] ^ 1].flow -= ans;
x = e[p[x]].u;
}
return ans;
}
int ISAP() {
int flow = 0, x = s;
for (int i = 1; i <= n; i++) num[dep[i]]++;
for (int i = 1; i <= cnt; i++) cur[i] = head[i];
while (dep[s] < n) {
if (x == t) {
flow += agument();
x = s;
}
int flag = 0;
for (int i = cur[x]; i; i = e[i].nxt)
if (e[i].cap > e[i].flow && dep[x] == dep[e[i].v] + 1) {
flag = 1;
p[e[i].v] = i;
cur[x] = i;
x = e[i].v;
break;
}
if (flag == 0) {
if (--num[dep[x]] == 0) break;
int mn = n - 1;
for (int i = head[x]; i; i = e[i].nxt)
if (e[i].cap > e[i].flow) mn = min(mn, dep[e[i].v]);
dep[x] = mn + 1;
num[dep[x]]++;
cur[x] = head[x];
if (x != s) x = e[p[x]].u;
}
}
return flow;
}
signed main() {
cin >> m >> n;
s = n + 1; t = n + 2;
int u, v;
for (int i = 1; i <= m; i++) {
add(s, i, 1); add(i, s, 0);
}
for (int i = m + 1; i <= n; i++) {
add(i, t, 1); add(t, i, 0);
}
while (cin >> u >> v) {
if (u == -1 && v == -1) break;
add(u, v, 1); add(v, u, 0);
}
bfs();
int ans = ISAP();
if (ans == 0) {
cout << "No Solution!" << endl;
return 0;
}
cout << ans << endl;
for (int i = 2 + n * 2; i <= cnt; i += 2)
if (e[i].flow == e[i].cap)
cout << e[i].u << " " << e[i].v << endl;
return 0;
}
P4001 [ICPC-Beijing 2006] 狼抓兔子
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#define INF 0x7fffffff
using namespace std;
const int maxn = 6e6 + 10;
int n, m, s, t, cnt = 1;
int head[maxn], vis[maxn];
int dep[maxn], num[maxn], cur[maxn], p[maxn];
struct node{
int u, v, nxt, cap, flow;
}e[maxn];
inline void add(int u, int v, int w) {
e[++cnt].u = u; e[cnt].v = v;
e[cnt].cap = w; e[cnt].flow = 0;
e[cnt].nxt = head[u]; head[u] = cnt;
}
inline void bfs() {
/*queue<int> q;
vis[t] = 1; dep[t] = 0;
q.push(t);
while (!q.empty()) {
int now = q.front(); q.pop();
for (int i = head[now]; i; i = e[i].nxt)
if (vis[e[i].v] == 0 && e[i].cap == 0) {
vis[e[i].v] = 1;
dep[e[i].v] = dep[now] + 1;
q.push(e[i].v);
}
}*/
queue<int> q;
memset(dep, -1, sizeof(dep));
dep[t] = 0;
q.push(t);
while (!q.empty()) {
int now = q.front(); q.pop();
for (int i = head[now]; i; i = e[i].nxt)
if (dep[e[i].v] == -1) {
dep[e[i].v] = dep[now] + 1;
q.push(e[i].v);
}
}
}
inline int agument() {
int x = t, ans = INF;
while (x != s) {
ans = min(ans, e[p[x]].cap - e[p[x]].flow);
x = e[p[x]].u;
}
x = t;
while (x != s) {
e[p[x]].flow += ans;
e[p[x] ^ 1].flow -= ans;
x = e[p[x]].u;
}
return ans;
}
int ISAP() {
int flow = 0, x = s;
for (int i = 1; i <= n; i++) num[dep[i]]++;
for (int i = 1; i <= cnt; i++) cur[i] = head[i];
while (dep[s] < n) {
if (x == t) {
flow += agument();
x = s;
}
int flag = 0;
for (int i = cur[x]; i; i = e[i].nxt)
if (e[i].cap > e[i].flow && dep[x] == dep[e[i].v] + 1) {
flag = 1;
p[e[i].v] = i;
cur[x] = i;
x = e[i].v;
break;
}
if (flag == 0) {
if (--num[dep[x]] == 0) break;
int mn = n - 1;
for (int i = head[x]; i; i = e[i].nxt)
if (e[i].cap > e[i].flow) mn = min(mn, dep[e[i].v]);
dep[x] = mn + 1;
num[dep[x]]++;
cur[x] = head[x];
if (x != s) x = e[p[x]].u;
}
}
return flow;
}
signed main() {
cin >> n >> m;
s = 1; t = n * m ;
for (int i = 1; i <= n; i++)
for (int j = 1; j < m; j++) {
int x;
cin >> x;
int u = (i - 1) * m + j;
int v = (i - 1) * m + j + 1;
add(u, v, x); add(v, u, x);
}
for (int i = 1; i < n; i++)
for (int j = 1; j <= m; j++) {
int x;
cin >> x;
int u = (i - 1) * m + j;
int v = i * m + j;
add(u, v, x); add(v, u, x);
}
for (int i = 1; i < n; i++)
for (int j = 1; j < m; j++) {
int x;
cin >> x;
int u = (i - 1) * m + j;
int v = i * m + j + 1;
add(u, v, x); add(v, u, x);
}
n = n * m;
bfs();
int ans = ISAP();
cout << ans << endl;
return 0;
}
费用流
均基于 dinic 算法实现
P3381 【模板】最小费用最大流
普通解法
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e7 + 10;
int n, m, s, t, cnt = 1, ret;
int head[maxn], vis[maxn], dis[maxn], cur[maxn];
struct node{
int v, nxt, cap, flow;
}e[maxn];
inline void add(int u, int v, int w, int c) {
e[++cnt].v = v;
e[cnt].flow = w; e[cnt].cap = c;
e[cnt].nxt = head[u]; head[u] = cnt;
}
inline bool spfa(int s, int t) {
for (int i = 1; i <= n; i++) cur[i] = head[i];
queue<int> q;
for (int i = 1; i <= n; i++) dis[i] = INF;
dis[s] = 0; vis[s] = 1;
q.push(s);
while (!q.empty()) {
int now = q.front(); q.pop();
vis[now] = 0;
for (int i = head[now]; i; i = e[i].nxt) {
int to = e[i].v;
if (e[i].flow && dis[to] > dis[now] + e[i].cap) {
dis[to] = dis[now] + e[i].cap;
if (vis[to]) continue;
vis[to] = 1;
q.push(to);
}
}
}
return dis[t] != INF;
}
int dfs(int u, int t, int flow) {
if (u == t) return flow;
vis[u] = 1;
int ans = 0;
for (int i = cur[u]; i && ans < flow; i = e[i].nxt) {
int v = e[i].v;
if (!vis[v] && e[i].flow && dis[v] == dis[u] + e[i].cap) {
int x = dfs(v, t, min(e[i].flow, flow - ans));
if (x) {
ret += x * e[i].cap;
e[i].flow -= x;
e[i ^ 1].flow += x;
ans += x;
}
}
}
vis[u] = 0;
return ans;
}
int mcmf(int s, int t) {
int ans = 0;
while (spfa(s, t)) {
int x;
while ((x = dfs(s, t, INF))) ans += x;
}
return ans;
}
int main() {
cin >> n >> m >> s >> t;
for (int i = 1; i <= m; i++) {
int u, v, w, c;
cin >> u >> v >> w >> c;
add(u, v, w, c); add(v, u, 0, -c);
}
int ans = mcmf(s, t);
cout << ans << " " << ret << endl;
return 0;
}
Primal-Dual 原始对偶算法
需要开 O2 才能过,还是不要用了 QAQ
#include <bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
const int maxn = 1e7 + 10;
int n, m, s, t, cnt = 1, maxf, minc;
int head[maxn], vis[maxn], dis[maxn], h[maxn];
struct node{
int v, nxt, cap, flow;
}e[maxn];
struct noda{
int v, e;
}p[maxn];
inline void add(int u, int v, int w, int c) {
e[++cnt].v = v;
e[cnt].flow = w; e[cnt].cap = c;
e[cnt].nxt = head[u]; head[u] = cnt;
}
inline void spfa() {
queue<int> q;
memset(h, 0x3f, sizeof(h));
h[s] = 0; vis[s] = 1;
q.push(s);
while (!q.empty()) {
int now = q.front(); q.pop();
vis[now] = 0;
for (int i = head[now]; i; i = e[i].nxt) {
int to = e[i].v;
if (e[i].flow && h[to] > h[now] + e[i].cap) {
h[to] = h[now] + e[i].cap;
if (vis[to]) continue;
vis[to] = 1;
q.push(to);
}
}
}
}
inline bool dijkstra() {
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
for (int i = 1; i <= n; i++) dis[i] = INF;
memset(vis, 0, sizeof(vis));
dis[s] = 0;
q.push(make_pair(0, s));
while (!q.empty()) {
int now = q.top().second; q.pop();
if (vis[now]) continue;
vis[now] = 1;
for (int i = head[now]; i; i = e[i].nxt) {
int to = e[i].v, nc = e[i].cap + h[now] - h[to];
if (e[i].flow && dis[to] > dis[now] + nc) {
dis[to] = dis[now] + nc;
p[to].v = now;
p[to].e = i;
if (!vis[to]) q.push(make_pair(dis[to], to));
}
}
}
return dis[t] != INF;
}
int main() {
cin >> n >> m >> s >> t;
for (int i = 1; i <= m; i++) {
int u, v, w, c;
cin >> u >> v >> w >> c;
add(u, v, w, c); add(v, u, 0, -c);
}
spfa();
while (dijkstra()) {
int minf = INF;
for (int i = 1; i <= n; i++) h[i] += dis[i];
for (int i = t; i != s; i = p[i].v) minf = min(minf, e[p[i].e].flow);
for (int i = t; i != s; i = p[i].v) {
e[p[i].e].flow -= minf;
e[p[i].e ^ 1].flow += minf;
}
maxf += minf;
minc += minf * h[t];
}
cout << maxf << " " << minc << endl;
return 0;
}
P4016 负载平衡问题
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e7 + 10;
int n, m, cnt = 1;
int head[maxn], vis[maxn], dis[maxn], cur[maxn];
long long sum, ret, a[maxn];
struct node{
int v, nxt, cap;
long long flow;
}e[maxn];
inline void add(int u, int v, long long w, int c) {
e[++cnt].v = v;
e[cnt].flow = w; e[cnt].cap = c;
e[cnt].nxt = head[u]; head[u] = cnt;
}
inline bool spfa(int s, int t) {
//for (int i = 0; i <= t; i++) cur[i] = head[i], dis[i] = INF;
memset(dis, 0x3f, sizeof(dis));
memcpy(cur, head, sizeof(head));
queue<int> q;
dis[s] = 0; vis[s] = 1;
q.push(s);
while (!q.empty()) {
int now = q.front(); q.pop();
vis[now] = 0;
for (int i = head[now]; i; i = e[i].nxt) {
int to = e[i].v;
if (e[i].flow && dis[to] > dis[now] + e[i].cap) {
dis[to] = dis[now] + e[i].cap;
if (vis[to]) continue;
vis[to] = 1;
q.push(to);
}
}
}
return dis[t] != INF;
}
long long dfs(int u, int t, long long flow) {
if (u == t) return flow;
vis[u] = 1;
long long ans = 0;
for (int i = cur[u]; i && ans < flow; i = e[i].nxt) {
int v = e[i].v;
if (!vis[v] && e[i].flow && dis[v] == dis[u] + e[i].cap) {
int x = dfs(v, t, min(e[i].flow, flow - ans));
if (x) {
ret += x * e[i].cap;
e[i].flow -= x;
e[i ^ 1].flow += x;
ans += x;
}
}
}
vis[u] = 0;
return ans;
}
void mcmf(int s, int t) {
int ans = 0;
while (spfa(s, t)) {
int x;
while ((x = dfs(s, t, INF))) ans += x;
//cout << "dfs: " << x << endl;
}
}
signed main() {
cin >> n;
int s, t;
s = 0; t = n + 1;
for (int i = 1; i <= n; i++) {
cin >> a[i];
sum += a[i];
}
sum /= n;
for (int i = 1; i <= n; i++) {
if (a[i] > sum) {
add(s, i, a[i] - sum, 0);
add(i, s, 0, 0);
} else if (a[i] < sum) {
add(i, t, sum - a[i], 0);
add(t, i, 0, 0);
}
if (i == 1) {
add(1, n, INF, 1);
add(n, 1, 0, -1);
add(n, 1, INF, 1);
add(1, n, 0, -1);
} else {
add(i - 1, i, INF, 1);
add(i, i - 1, 0, -1);
add(i, i - 1, INF, 1);
add(i - 1, i, 0, -1);
}
}
mcmf(s, t);
cout << ret << endl;
return 0;
}
最小割
P1345 [USACO5.4]奶牛的电信Telecowmunication
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e7 + 10;
int n, m, s, t, cnt = 1;
int head[maxn], dep[maxn], cur[maxn];
struct node{
int v, flow, nxt;
}e[maxn];
inline void add(int u, int v, int w) {
e[++cnt].v = v; e[cnt].flow = w;
e[cnt].nxt = head[u]; head[u] = cnt;
}
int bfs(int s, int t) {
memset(dep, 0, sizeof(dep));
memcpy(cur, head, sizeof(head));
queue<int> q;
dep[s] = 1;
q.push(s);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v;
if (e[i].flow && !dep[v]) {
q.push(v);
dep[v] = dep[u] + 1;
}
}
}
return dep[t];
}
int dfs(int u, int t, int flow) {
if (u == t) return flow;
int ans = 0;
for (int i = head[u]; i && ans < flow; i = e[i].nxt) {
int v = e[i].v;
if (e[i].flow && dep[v] == dep[u] + 1) {
int x = dfs(v, t, min(e[i].flow, flow - ans));
if (x) {
e[i].flow -= x;
e[i ^ 1].flow += x;
ans += x;
}
}
}
if (ans < flow) dep[u] = -1;
return ans;
}
int dinic(int s, int t) {
int ans = 0;
while (bfs(s, t)) {
int x;
while ((x = dfs(s, t, INF))) ans += x;
}
return ans;
}
int main() {
cin >> n >> m >> s >> t;
s += n;
for (int i = 1; i <= n; i++) {
add(i, i + n, 1); add(i + n, i, 0);
}
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
add(u + n, v, INF);
add(v, u + n, 0);
add(v + n, u, INF);
add(u, v + n, 0);
}
int ans = dinic(s, t);
cout << ans << endl;
return 0;
}
P2057 [SHOI2007]善意的投票 / [JLOI2010]冠军调查
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e7 + 10;
int n, m, s, t, cnt = 1;
int head[maxn], dep[maxn], cur[maxn];
struct node{
int v, flow, nxt;
}e[maxn];
inline void add(int u, int v, int w) {
e[++cnt].v = v; e[cnt].flow = w;
e[cnt].nxt = head[u]; head[u] = cnt;
}
int bfs(int s, int t) {
memset(dep, 0, sizeof(dep));
memcpy(cur, head, sizeof(head));
queue<int> q;
dep[s] = 1;
q.push(s);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v;
if (e[i].flow && !dep[v]) {
q.push(v);
dep[v] = dep[u] + 1;
}
}
}
return dep[t];
}
int dfs(int u, int t, int flow) {
if (u == t) return flow;
int ans = 0;
for (int i = head[u]; i && ans < flow; i = e[i].nxt) {
int v = e[i].v;
if (e[i].flow && dep[v] == dep[u] + 1) {
int x = dfs(v, t, min(e[i].flow, flow - ans));
if (x) {
e[i].flow -= x;
e[i ^ 1].flow += x;
ans += x;
}
}
}
if (ans < flow) dep[u] = -1;
return ans;
}
int dinic(int s, int t) {
int ans = 0;
while (bfs(s, t)) {
int x;
while ((x = dfs(s, t, INF))) ans += x;
}
return ans;
}
int main() {
cin >> n >> m;
s = 0; t = n + 1;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
if (x == 1) add(s, i, 1), add(i, s, 0);
else add(i, t, 1), add(t, i, 0);
}
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
add(u, v, 1); add(v, u, 0);
add(v, u, 1); add(u, v, 0);
}
int ans = dinic(s, t);
cout << ans << endl;
return 0;
}