Network-flows
Ford-Fulkerson算法
typedef long long ll;
const int N = 1e5 + 10;
int head[N], to[N], nex[N], flow[N], cnt;
int vis[N], n, m, s, t;
void add(int x, int y, int w) {
to[cnt] = y;
nex[cnt] = head[x];
flow[cnt] = w;
head[x] = cnt++;
}
ll dfs(int rt, ll now) {
if(rt == t) return now;
vis[rt] = 1;
for(int i = head[rt]; ~i; i = nex[i]) {
if(!vis[to[i]] && flow[i] > 0) {
ll cur = dfs(to[i], min(now, 1ll * flow[i]));
if(cur != -1) {
flow[i] -= cur;
flow[i ^ 1] += cur;
return cur;
}
}
}
return -1;
}
ll solve() {
ll ans = 0, cur;
while(true) {
cur = dfs(s, 0x3f3f3f3f3f3f3f3f);
if(cur == -1) return ans;
ans += cur;
memset(vis, 0, sizeof vis);
}
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head);
n = read(), m = read(), s = read(), t = read();
for(int i = 1; i <= m; i++) {
int x = read(), y = read(), w = read();
add(x, y, w);
add(y, x, 0);
}
printf("%lld\n", solve());
return 0;
}
Edmond-Karp
typedef long long ll;
const int N = 1e5 + 10;
ll head[N], to[N], nex[N], flow[N], cnt;
ll last[N], n, m, s, t;
ll flo[N];
void add(int x, int y, int w) {
to[cnt] = y;
nex[cnt] = head[x];
flow[cnt] = w;
head[x] = cnt++;
}
bool bfs() {
queue<int> q;
q.push(s);
flo[s] = 0x3f3f3f3f3f3f3f3f;
memset(last, -1, sizeof last);
while(q.size()) {
int temp = q.front();
q.pop();
if(temp == t) {
break;
}
for(int i = head[temp]; ~i; i = nex[i]) {
if(last[to[i]] == -1 && flow[i]) {
last[to[i]] = i;
flo[to[i]] = min(flo[temp], 1ll * flow[i]);
q.push(to[i]);
}
}
}
return last[t] != -1;
}
ll solve() {
ll ans = 0;
while(bfs()) {
ans += flo[t];
for(int i = t; i != s; i = to[last[i] ^ 1]) {
flow[last[i]] -= flo[t];
flow[last[i] ^ 1] += flo[t];
}
}
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head);
n = read(), m = read(), s = read(), t = read();
for(int i = 1; i <= m; i++) {
int x = read(), y = read(), w = read();
add(x, y, w);
add(y, x, 0);
}
printf("%lld\n", solve());
return 0;
}
Dinic
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
struct max_flow {
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, dep[N], x[N], y[N], f[N];
void init() {
memset(head, -1, sizeof head), cnt = 0;
}
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
// void print(int rt) {
// for(int i = head[rt]; ~i; i = nex[i]) {
// if(cap[i] || to[i] == s || to[i] == rt + m) continue;
// printf(" %d", to[i] - m);
// print(to[i] - m);
// return ;
// }
// }
}dinic;
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
return 0;
}
Mcmf
Spfa
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
struct min_cost_max_flow {
int head[N], cap[N], to[N], nex[N], value[N], cnt;
int s, t, dis[N], vis[N], flow[N], pre[N];
void init() {
memset(head, -1, sizeof head), cnt = 0;
}
void Add(int x, int y, int w, int c) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int w, int c) {
Add(x, y, w, c);
Add(y, x, -w, 0);
}
bool spfa() {
queue<int> q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
q.push(s), dis[s] = 0, vis[s] = 1;
flow[s] = 1 << 30;
while(q.size()) {
int rt = q.front();
q.pop(), vis[rt] = 0;
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] && dis[to[i]] > dis[rt] + value[i]) {
dis[to[i]] = dis[rt] + value[i];
flow[to[i]] = min(flow[rt], cap[i]);
pre[to[i]] = i;
if(!vis[to[i]]) {
vis[to[i]] = 1;
q.push(to[i]);
}
}
}
}
return dis[t] != 0x3f3f3f3f;
}
pii Mcmf() {
int res = 0, ans = 0;
while(spfa()) {
int cur = flow[t];
res += cur, ans += dis[t] * cur;
int now = t;
while(now != s) {
cap[pre[now]] -= cur;
cap[pre[now] ^ 1] += cur;
now = to[pre[now] ^ 1];
}
}
return make_pair(res, ans);
}
}mcmf;
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
return 0;
}
Dijkstra
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 5e3 + 10, inf = 0x3f3f3f3f;
struct edge {
int to, capacity, cost, rev;
edge() {}
edge(int to = 0, int _capacity = 0, int _cost = 0, int _rev = 0) :to(to), capacity(_capacity), cost(_cost), rev(_rev) {}
};
struct Min_Cost_Max_Flow {
int V, s, t, H[N + 5], dis[N + 5], PreV[N + 5], PreE[N + 5];
vector<edge> G[N + 5];
void init(int n) {
V = n;
for (int i = 0; i <= V; ++i)G[i].clear();
}
void add(int from, int to, int cost, int cap) {
G[from].push_back(edge(to, cap, cost, G[to].size()));
G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
}
pii mcmf() {
int res = 0, f = inf, flow = 0; fill(H, H + 1 + V, 0);
while (f) {
priority_queue <pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>> > q;
fill(dis, dis + 1 + V, inf);
dis[s] = 0; q.push(pair<int, int>(0, s));
while (!q.empty()) {
pair<int, int> now = q.top(); q.pop();
int v = now.second;
if (dis[v] < now.first)continue;
for (int i = 0; i < G[v].size(); ++i) {
edge& e = G[v][i];
if (e.capacity > 0 && dis[e.to] > dis[v] + e.cost + H[v] - H[e.to]) {
dis[e.to] = dis[v] + e.cost + H[v] - H[e.to];
PreV[e.to] = v;
PreE[e.to] = i;
q.push(pair<int, int>(dis[e.to], e.to));
}
}
}
if (dis[t] == inf)break;
for (int i = 0; i <= V; ++i)H[i] += dis[i];
int d = f;
for (int v = t; v != s; v = PreV[v])d = min(d, G[PreV[v]][PreE[v]].capacity);
f -= d; flow += d; res += d*H[t];
for (int v = t; v != s; v = PreV[v]) {
edge& e = G[PreV[v]][PreE[v]];
e.capacity -= d;
G[v][e.rev].capacity += d;
}
}
return make_pair(flow, res);
}
}mcmf;
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
return 0;
}
P2756 飞行员配对方案问题(二分图匹配)
二分图匹配问题然后输出匹配方案。
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, dep[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = 0;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head);
scanf("%d %d", &m, &n);
cnt = 0, s = 0, t = n + 1;
for(int i = 1; i <= m; i++) {
add(s, i, 1);
}
for(int i = m + 1; i <= n; i++) {
add(i, t, 1);
}
int tot = cnt;
int x, y;
while(scanf("%d %d", &x, &y) && x != -1) {
add(x, y, 1);
}
int ans = Dinic();
printf("%d\n", ans);
for(int i = tot; i < cnt; i += 2) {
if(cap[i] == 0 && cap[i ^ 1] == 1) {
printf("%d %d\n", to[i ^ 1], to[i]);
}
}
return 0;
}
P5039 [SHOI2010]最小生成树
我们要使 a − b a-b a−b出现在最小生成树集合中那么,必然有 a − > b a -> b a−>b的所有路径中,每个路径中一定有一条边是大于 a − b a-b a−b边的权值的,
对于每种操作,我们可以看作对选定的边进行 + 1操作,所以我们考虑如何将这个问题转化为网络流模型,
首先对于边权大于w[lab]的边是一定没有影响的,我们考虑边权小于w[a, b]的情况,
我们可以考虑用 w [ l a b ] − w [ n o w ] + 1 w[lab] - w[now] + 1 w[lab]−w[now]+1为 n o w a , n o w b now_a, now_b nowa,nowb两点间的流量的,然后跑一遍 l a − > l b l_a -> l_b la−>lb的最小割就行了,
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, l, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = 0;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head);
scanf("%d %d %d", &n, &m, &l);
for(int i = 1; i <= m; i++) {
scanf("%d %d %d", &x[i], &y[i], &f[i]);
}
s = x[l], t = y[l];
for(int i = 1; i <= m; i++) {
if(i != l && f[i] <= f[l]) {
Add(x[i], y[i], f[l] - f[i] + 1);
Add(y[i], x[i], f[l] - f[i] + 1);
}
}
printf("%d\n", Dinic());
return 0;
}
P5934 [清华集训2012]最小生成树
这道题目与上一道不同的有两点,
- 可能出现,可选这条边,可不选这条边,那就要使能到这两个点的所有路径中都有一条的权值 ≥ l \geq l ≥l了。
- 直接删边,代价改成 1 1 1就好了。
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, l, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = 0;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head);
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
scanf("%d %d %d", &x[i], &y[i], &f[i]);
}
scanf("%d %d %d", &s, &t, &l);
for(int i = 1; i <= m; i++) {
if(f[i] < l) {
Add(x[i], y[i], 1);
Add(y[i], x[i], 1);
}
}
int ans = Dinic();
memset(head, -1, sizeof head), cnt = 0;
for(int i = 1; i <= m; i++) {
if(f[i] > l) {
Add(x[i], y[i], 1);
Add(y[i], x[i], 1);
}
}
ans += Dinic();
printf("%d\n", ans);
return 0;
}
#6001. 「网络流 24 题」太空飞行计划
最大权闭合子图模板
S S S点连向正权值的点(权值累加),负权值的点连向 T T T,然后在每个关系中建立流量为无穷的有向边。
跑一遍最大流,最大权值为(累加的权值 - 最小割(最大流)), d e p dep dep数组标记为不为 − 1 -1 −1的点,即被选中的点。
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, l, ans, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head);
scanf("%d %d", &n, &m);
s = 0, t = n + m + 1;
for(int i = 1, x; i <= n; i++) {
scanf("%d", &x);
add(s, i, x);
ans += x;
while(getchar() == ' ') {
scanf("%d", &x);
add(i, n + x, inf);
}
}
for(int i = 1, x; i <= m; i++) {
scanf("%d", &x);
add(n + i, t, x);
}
ans -= Dinic();
for(int i = 1, flag = 0; i <= n; i++) {
if(dep[i] != -1) {
if(!flag) {
flag = 1;
}
else {
printf(" ");
}
printf("%d", i);
}
}
puts("");
for(int i = n + 1, flag = 0; i <= n + m; i++) {
if(dep[i] != -1) {
if(!flag) {
flag = 1;
}
else {
printf(" ");
}
printf("%d", i - n);
}
}
printf("\n%d\n", ans);
return 0;
}
Firing
/*
Author : lifehappy
*/
// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define int long long
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, dep[N], value[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
signed main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
while(scanf("%lld %lld", &n, &m) != EOF) {
memset(head, -1, sizeof head), cnt = 0;
s = 0, t = n + 1;
int ans = 0;
for(int i = 1; i <= n; i++) {
int value;
scanf("%lld", &value);
if(value > 0) {
ans += value;
add(s, i, value);
}
else {
add(i, t, -value);
}
}
for(int i = 1; i <= m; i++) {
int x, y;
scanf("%lld %lld", &x, &y);
add(x, y, inf * inf);
}
ans -= Dinic();
int res = 0;
for(int i = 1; i <= n; i++) {
if(dep[i] != -1) {
res++;
}
}
printf("%lld %lld\n", res, ans);
}
return 0;
}
[网络流 24 题]最小路径覆盖
最小路径数为 顶 点 个 数 − 最 大 匹 配 数 顶点个数- 最大匹配数 顶点个数−最大匹配数
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
void print(int rt) {
printf("%d ", rt);
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] || to[i] == s || to[i] == rt + n) continue;
print(to[i] - n);
return ;
}
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head), cnt = 0;
scanf("%d %d", &n, &m);
s = 0, t = 2 * n + 1;
for(int i = 1; i <= n; i++) {
add(s, i, 1);
add(i + n, t, 1);
}
for(int i = 1; i <= m; i++) {
int x, y;
scanf("%d %d", &x, &y);
add(x, y + n, 1);
}
int ans = Dinic();
for(int i = 1; i <= n; i++) {
int flag = 1;
for(int j = head[i + n]; ~j; j = nex[j]) {
if(cap[j] && to[j] != i && to[j] != t) {
flag = 0;
break;
}
}
if(flag) {
print(i);
puts("");
}
}
printf("%d\n", n - ans);
return 0;
}
[网络流 24 题 魔术球]
最小路径覆盖的变形题。
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, tot, ans, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while (q.size()) {
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = nex[i]) {
if (dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if (rt == t)
return flow;
int res = flow;
for (int i = head[rt]; ~i; i = nex[i]) {
if (dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if (temp == 0)
dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if (res == 0)
break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while (bfs()) {
ans += dfs(s, inf);
}
return ans;
}
void print(int rt) {
for (int i = head[rt]; ~i; i = nex[i]) {
if (cap[i] || to[i] == s || to[i] == rt + m)
continue;
printf(" %d", to[i] - m);
print(to[i] - m);
return ;
}
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head), cnt = 0;
scanf("%d", &n);
tot = 0, m = 5000, s = 0, t = 10001;
while (++tot) {
add(s, tot, 1), add(tot + m, t, 1);
for (int i = 1; i < tot; i++) {
if (sqrt(i + tot) == int(sqrt(i + tot))) {
add(i, tot + m, 1);
}
}
ans += Dinic();
if (tot - ans > n)
break;
}
printf("%d\n", tot - 1);
for (int i = 1; i < tot; i++) {
int flag = 1;
for (int j = head[i + m]; ~j; j = nex[j]) {
if (cap[j] && to[j] != i && to[j] != t) {
flag = 0;
break;
}
}
if (flag) {
printf("%d", i);
print(i);
puts("");
}
}
return 0;
}
[网络流 24 题]圆桌聚餐
挺好想的这题,直接二分图匹配,然后输出方案数就行了。
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
void print(int rt) {
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] || to[i] == s || to[i] == rt + m) continue;
printf(" %d", to[i] - m);
print(to[i] - m);
return ;
}
}
vector<int> res[300];
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head), cnt = 0;
scanf("%d %d", &m, &n);
s = 0, t = n + m + 1;
int sum1 = 0;
for(int i = 1; i <= m; i++) {
int x;
scanf("%d", &x);
add(i + n, t, x);
sum1 += x;
}
int sum2 = 0;
for(int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
add(s, i, x);
sum2 += x;
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
add(i, j + n, 1);
}
}
int ans = Dinic();
if(ans != min(sum1, sum2)) {
puts("0");
return 0;
}
printf("%d\n", 1);
for(int i = 1; i <= n; i++) {
for(int j = head[i]; ~j; j = nex[j]) {
if(cap[j] == 0 && to[j] != s) {
res[to[j] - n].push_back(i);
}
}
}
for(int i = 1; i <= m; i++) {
for(auto it : res[i]) {
printf("%d ", it);
}
puts("");
}
return 0;
}
[网络流 24 题]试题库
有点像二分图最大匹配,其实好像就是吧。
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
void print(int rt) {
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] || to[i] == s || to[i] == rt + m) continue;
printf(" %d", to[i] - m);
print(to[i] - m);
return ;
}
}
vector<int> res[50];
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head), cnt = 0;
scanf("%d %d", &m, &n);
s = 0, t = n + m + 1;
int sum = 0;
for(int i = 1; i <= m; i++) {
int x;
scanf("%d", &x);
add(n + i, t, x);
sum += x;
}
for(int i = 1; i <= n; i++) {
int tot, x;
scanf("%d", &tot);
add(s, i, 1);
for(int j = 1; j <= tot; j++) {
scanf("%d", &x);
add(i, x + n, 1);
}
}
int ans = Dinic();
if(ans != sum) {
puts("No Solution!");
return 0;
}
for(int i = 1; i <= n; i++) {
for(int j = head[i]; ~j; j = nex[j]) {
if(!cap[j] && to[j] != s) {
res[to[j] - n].push_back(i);
}
}
}
for(int i = 1; i <= m; i++) {
printf("%d: ", i);
for(auto it : res[i]) {
printf("%d ", it);
}
puts("");
}
return 0;
}
[网络流 24 题]最长递增子序列
先跑一次 d p dp dp求得 s s s,
对于问题二,先拆点然后对所有 d p [ i ] = 1 dp[i] = 1 dp[i]=1的连一条 a d d ( s , i , 1 ) add(s, i, 1) add(s,i,1)的边,对所有 d p [ i ] = s dp[i] = s dp[i]=s的点连一条 a d d ( i + n , t , 1 ) add(i + n, t, 1) add(i+n,t,1)的边
然后对 i < j , a [ i ] ≤ a [ j ] , d p [ i ] + 1 = d p [ j ] i < j, a[i] \leq a[j],dp[i] + 1 = dp[j] i<j,a[i]≤a[j],dp[i]+1=dp[j],连一条 a d d ( i + n , j , 1 ) add(i + n, j, 1) add(i+n,j,1)的边,然后跑一遍最大流即可了。
对于问题二, a d d ( s , 1 , i n f ) , a d d ( 1 , n + 1 , i n f ) add(s, 1, inf), add(1, n + 1, inf) add(s,1,inf),add(1,n+1,inf),如果 d p [ n ] = s dp[n] = s dp[n]=s, a d d ( n , n + n , i n f ) , a d d ( n + n , T , i n f ) add(n, n + n, inf), add(n + n, T, inf) add(n,n+n,inf),add(n+n,T,inf)然后跑一遍最大流即可。
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, res, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
void print(int rt) {
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] || to[i] == s || to[i] == rt + m) continue;
printf(" %d", to[i] - m);
print(to[i] - m);
return ;
}
}
const int N1 = 510;
int a[N], dp[N];
void solve1() {
for(int i = 1; i <= n; i++) {
dp[i] = 1;
for(int j = 1; j < i; j++) {
if(a[i] >= a[j]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
res = max(res, dp[i]);
}
printf("%d\n", res);
}
int solve2() {
memset(head, -1, sizeof head), cnt = 0, s = 0, t = 2 * n + 1;
for(int i = 1; i <= n; i++) {
if(dp[i] == 1) {
add(s, i, 1);
}
if(dp[i] == res) {
add(i + n, t, 1);
}
add(i, i + n, 1);
for(int j = i + 1; j <= n; j++) {
if(a[j] >= a[i] && dp[i] + 1 == dp[j]) {
add(i + n, j, 1);
}
}
}
int ans = Dinic();
printf("%d\n", ans);
return ans;
}
void solve3() {
int ans = solve2();
add(s, 1, inf), add(1, 1 + n, inf);
if(dp[n] == res) {
add(n, n + n, inf);
add(n + n, t, inf);
}
printf("%d\n", Dinic() + ans);
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
if(n == 1) {
puts("1\n1\n1");
return 0;
}
solve1();
solve3();
return 0;
}
[网络流 24 题]方格取数
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
int head[N], to[N], nex[N], cap[N], cnt;
int s, t, n, m, dep[N], x[N], y[N], f[N];
void Add(int x, int y, int c) {
to[cnt] = y;
nex[cnt] = head[x];
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int c) {
Add(x, y, c);
Add(y, x, 0);
}
bool bfs() {
queue<int> q;
memset(dep, -1, sizeof dep);
dep[s] = 0;
q.push(s);
while(q.size()) {
int u = q.front();
q.pop();
for(int i = head[u]; ~i; i = nex[i]) {
if(dep[to[i]] == -1 && cap[i]) {
q.push(to[i]);
dep[to[i]] = dep[u] + 1;
}
}
}
return dep[t] != -1;
}
int dfs(int rt, int flow) {
if(rt == t) return flow;
int res = flow;
for(int i = head[rt]; ~i; i = nex[i]) {
if(dep[to[i]] == dep[rt] + 1 && cap[i]) {
int temp = dfs(to[i], min(res, cap[i]));
if(temp == 0) dep[to[i]] = -1;
res -= temp;
cap[i] -= temp;
cap[i ^ 1] += temp;
}
if(res == 0) break;
}
return flow - res;
}
int Dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
void print(int rt) {
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] || to[i] == s || to[i] == rt + m) continue;
printf(" %d", to[i] - m);
print(to[i] - m);
return ;
}
}
const int ax[4] = {1, -1, 0, 0}, ay[4] = {0, 0, 1, -1};
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head), cnt = 0;
scanf("%d %d", &n, &m);
s = 0, t = n * m + 1;
int sum = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
int x;
scanf("%d", &x);
sum += x;
if((i + j) & 1) {
add(s, (i - 1) * m + j, x);
for(int k = 0; k < 4; k++) {
int x = i + ax[k], y = j + ay[k];
if(x < 1 || x > n || y < 1 || y > m) continue;
add((i - 1) * m + j, (x - 1) * m + y, inf);
}
}
else {
add((i - 1) * m + j, t, x);
}
}
}
printf("%d\n", sum - Dinic());
return 0;
}
[网络流 24 题]餐巾计划
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
const int N = 5e5 + 10;
ll inf = 0x3f3f3f3f3f3f3f3f;
ll head[N], cap[N], to[N], nex[N], value[N], cnt;
ll n, m, s, t, dis[N], vis[N], flow[N], pre[N];
void Add(int x, int y, int w, int c) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int w, int c) {
Add(x, y, w, c);
Add(y, x, -w, 0);
}
bool spfa() {
queue<int> q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
q.push(s), dis[s] = 0, vis[s] = 1;
flow[s] = 1 << 30;
while(q.size()) {
int rt = q.front();
q.pop(), vis[rt] = 0;
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] && dis[to[i]] > dis[rt] + value[i]) {
dis[to[i]] = dis[rt] + value[i];
flow[to[i]] = min(flow[rt], cap[i]);
pre[to[i]] = i;
if(!vis[to[i]]) {
vis[to[i]] = 1;
q.push(to[i]);
}
}
}
}
return dis[t] != 0x3f3f3f3f3f3f3f3f;
}
pii Mcmf() {
ll res = 0, ans = 0;
while(spfa()) {
int cur = flow[t];
res += cur, ans += dis[t] * cur;
int now = t;
while(now != s) {
cap[pre[now]] -= cur;
cap[pre[now] ^ 1] += cur;
now = to[pre[now] ^ 1];
}
}
return make_pair(res, ans);
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head), cnt = 0;
int P, M, F, N, S;
scanf("%d", &n);
s = 0, t = 2 * n + 1;
for(int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
add(s, i, 0, x);
add(i + n, t, 0, x);
}
scanf("%d %d %d %d %d", &P, &M, &F, &N, &S);
for(int i = 1; i <= n; i++) {
add(s, i + n, P, inf);
if(i + 1 <= n) add(i, i + 1, 0, inf);
if(i + M <= n) add(i, i + M + n, F, inf);
if(i + N <= n) add(i, i + N + n, S, inf);
}
pii ans = Mcmf();
// printf("%d\n", ans.second);
cout << ans.second << "\n";
return 0;
}
[网络流 24 题]数字梯形
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
int head[N], cap[N], to[N], nex[N], value[N], cnt;
int n, m, s, t, dis[N], vis[N], flow[N], pre[N];
void Add(int x, int y, int w, int c) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int w, int c) {
Add(x, y, w, c);
Add(y, x, -w, 0);
}
bool spfa() {
queue<int> q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
q.push(s), dis[s] = 0, vis[s] = 1;
flow[s] = 1 << 30;
while(q.size()) {
int rt = q.front();
q.pop(), vis[rt] = 0;
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] && dis[to[i]] > dis[rt] + value[i]) {
dis[to[i]] = dis[rt] + value[i];
flow[to[i]] = min(flow[rt], cap[i]);
pre[to[i]] = i;
if(!vis[to[i]]) {
vis[to[i]] = 1;
q.push(to[i]);
}
}
}
}
return dis[t] != 0x3f3f3f3f;
}
pii Mcmf() {
int res = 0, ans = 0;
while(spfa()) {
int cur = flow[t];
res += cur, ans += dis[t] * cur;
int now = t;
while(now != s) {
cap[pre[now]] -= cur;
cap[pre[now] ^ 1] += cur;
now = to[pre[now] ^ 1];
}
}
return make_pair(res, ans);
}
int a[50][50], id[50][50], tot;
void solve1() {
memset(head, -1, sizeof head), cnt = 0;
s = 0, t = 2 * tot + 1;
for(int i = 1; i <= n; i++) {
add(s, id[1][i], 0, 1);
}
for(int i = 1; i < m; i++) {
for(int j = 1; j <= n + i - 1; j++) {
add(id[i][j], id[i][j] + tot, -a[i][j], 1);
add(id[i][j] + tot, id[i + 1][j], 0, 1);
add(id[i][j] + tot, id[i + 1][j + 1], 0, 1);
}
}
for(int i = 1; i <= n + m - 1; i++) {
add(id[m][i], id[m][i] + tot, -a[m][i], 1);
add(id[m][i] + tot, t, 0, 1);
}
printf("%d\n", -Mcmf().second);
}
void solve2() {
memset(head, -1, sizeof head), cnt = 0;
s = 0, t = 2 * tot + 1;
for(int i = 1; i <= n; i++) {
add(s, id[1][i], 0, 1);
}
for(int i = 1; i < m; i++) {
for(int j = 1; j <= n + i - 1; j++) {
add(id[i][j], id[i][j] + tot, -a[i][j], inf);
add(id[i][j] + tot, id[i + 1][j], 0, 1);
add(id[i][j] + tot, id[i + 1][j + 1], 0, 1);
}
}
for(int i = 1; i <= n + m - 1; i++) {
add(id[m][i], id[m][i] + tot, -a[m][i], inf);
add(id[m][i] + tot, t, 0, inf);
}
printf("%d\n", -Mcmf().second);
}
void solve3() {
memset(head, -1, sizeof head), cnt = 0;
s = 0, t = 2 * tot + 1;
for(int i = 1; i <= n; i++) {
add(s, id[1][i], 0, 1);
}
for(int i = 1; i < m; i++) {
for(int j = 1; j <= n + i - 1; j++) {
add(id[i][j], id[i][j] + tot, -a[i][j], inf);
add(id[i][j] + tot, id[i + 1][j], 0, inf);
add(id[i][j] + tot, id[i + 1][j + 1], 0, inf);
}
}
for(int i = 1; i <= n + m - 1; i++) {
add(id[m][i], id[m][i] + tot, -a[m][i], inf);
add(id[m][i] + tot, t, 0, inf);
}
printf("%d\n", -Mcmf().second);
}
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
for(int j = 1; j <= n + i - 1; j++) {
scanf("%d", &a[i][j]);
id[i][j] = ++tot;
}
}
solve1();
solve2();
solve3();
return 0;
}
[网络流 24 题]运输问题
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
int head[N], cap[N], to[N], nex[N], value[N], cnt;
int n, m, s, t, dis[N], vis[N], flow[N], pre[N];
void Add(int x, int y, int w, int c) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int w, int c) {
Add(x, y, w, c);
Add(y, x, -w, 0);
}
bool spfa() {
queue<int> q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
q.push(s), dis[s] = 0, vis[s] = 1;
flow[s] = 1 << 30;
while(q.size()) {
int rt = q.front();
q.pop(), vis[rt] = 0;
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] && dis[to[i]] > dis[rt] + value[i]) {
dis[to[i]] = dis[rt] + value[i];
flow[to[i]] = min(flow[rt], cap[i]);
pre[to[i]] = i;
if(!vis[to[i]]) {
vis[to[i]] = 1;
q.push(to[i]);
}
}
}
}
return dis[t] != 0x3f3f3f3f;
}
pii Mcmf() {
int res = 0, ans = 0;
while(spfa()) {
int cur = flow[t];
res += cur, ans += dis[t] * cur;
int now = t;
while(now != s) {
cap[pre[now]] -= cur;
cap[pre[now] ^ 1] += cur;
now = to[pre[now] ^ 1];
}
}
return make_pair(res, ans);
}
const int N1 = 110;
int a[N1], b[N1], x[N1][N1];
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
memset(head, -1, sizeof head), cnt = 0;
scanf("%d %d", &n, &m);
s = 0, t = n + m + 1;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
add(s, i, 0, a[i]);
}
for(int i = 1; i <= m; i++) {
scanf("%d", &b[i]);
add(i + n, t, 0, b[i]);
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
scanf("%d", &x[i][j]);
add(i, j + n, x[i][j], inf);
}
}
printf("%d\n", Mcmf().second);
memset(head, -1, sizeof head), cnt = 0;
for(int i = 1; i <= n; i++) {
add(s, i, 0, a[i]);
}
for(int i = 1; i <= m; i++) {
add(i + n, t, 0, b[i]);
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
add(i, j + n, -x[i][j], inf);
}
}
printf("%d\n", -Mcmf().second);
return 0;
}
[网络流 24 题]分配问题
/*
Author : lifehappy
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 5e5 + 10, inf = 0x3f3f3f3f;
int head[N], cap[N], to[N], nex[N], value[N], cnt;
int n, m, s, t, dis[N], vis[N], flow[N], pre[N];
void Add(int x, int y, int w, int c) {
to[cnt] = y;
nex[cnt] = head[x];
value[cnt] = w;
cap[cnt] = c;
head[x] = cnt++;
}
void add(int x, int y, int w, int c) {
Add(x, y, w, c);
Add(y, x, -w, 0);
}
bool spfa() {
queue<int> q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
q.push(s), dis[s] = 0, vis[s] = 1;
flow[s] = 1 << 30;
while(q.size()) {
int rt = q.front();
q.pop(), vis[rt] = 0;
for(int i = head[rt]; ~i; i = nex[i]) {
if(cap[i] && dis[to[i]] > dis[rt] + value[i]) {
dis[to[i]] = dis[rt] + value[i];
flow[to[i]] = min(flow[rt], cap[i]);
pre[to[i]] = i;
if(!vis[to[i]]) {
vis[to[i]] = 1;
q.push(to[i]);
}
}
}
}
return dis[t] != 0x3f3f3f3f;
}
pii Mcmf() {
int res = 0, ans = 0;
while(spfa()) {
int cur = flow[t];
res += cur, ans += dis[t] * cur;
int now = t;
while(now != s) {
cap[pre[now]] -= cur;
cap[pre[now] ^ 1] += cur;
now = to[pre[now] ^ 1];
}
}
return make_pair(res, ans);
}
const int N1 = 110;
int x[N1][N1];
int main() {
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
scanf("%d", &x[i][j]);
}
}
s = 0, t = n + n + 1;
memset(head, -1, sizeof head), cnt = 0;
for(int i = 1; i <= n; i++) {
add(s, i, 0, 1);
}
for(int i = 1; i <= n; i++) {
add(i + n, t, 0, 1);
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
add(i, j + n, x[i][j], 1);
}
}
printf("%d\n", Mcmf().second);
memset(head, -1, sizeof head), cnt = 0;
for(int i = 1; i <= n; i++) {
add(s, i, 0, 1);
}
for(int i = 1; i <= n; i++) {
add(i + n, t, 0, 1);
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
add(i, j + n, -x[i][j], 1);
}
}
printf("%d\n", -Mcmf().second);
return 0;
}