网络流
了解可行流,最大流,增广路,以及惨量网络的两条边
什么是割,最小割最大流定理:网络流的最大流量等于最小割的容量
DINIC算法 code
// Codevs 1993
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
using namespace std;
const int max_n = 220;
const int max_m = 220;
const int max_e = max_m * 2;
const int inf = 1e9;
int point[max_n], nxt[max_e], v[max_e], remain[max_e], tot;
int cur[max_n], deep[max_n], n, m;
inline int getnum() {
char c; int ans = 0;
while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
ans = c - '0';
while (isdigit(c = getchar())) ans = ans * 10 + c - '0';
return ans;
}
inline void addedge(int x, int y, int cap) {
tot++; nxt[tot] = point[x]; point[x] = tot; v[tot] = y; remain[tot] = cap;
tot++; nxt[tot] = point[y]; point[y] = tot; v[tot] = x; remain[tot] = 0;
}
inline bool bfs(int s, int t) {
memset(deep, 0x7f, sizeof(deep));
for (int i = 1; i <= n; i++)
cur[i] = point[i];
deep[s] = 0;
queue<int> q;
q.push(s);
while (!q.empty()) {
int now = q.front(); q.pop();
for (int tmp = point[now]; tmp != -1; tmp = nxt[tmp])
if (deep[v[tmp]] > inf && remain[tmp])
deep[v[tmp]] = deep[now] + 1, q.push(v[tmp]);
}
return deep[t] < inf;
}
int dfs(int now, int t, int limit) {
if (!limit || now == t) return limit;
int flow = 0, f;
for (int tmp = cur[now]; tmp != -1; tmp = nxt[tmp]) {
cur[now] = tmp;
if (deep[v[tmp]] == deep[now] + 1 && (f = dfs(v[tmp], t, min(limit, remain[tmp])))) {
flow += f;
limit -= f;
remain[tmp] -= f;
remain[tmp ^ 1] += f;
if (!limit) break;
}
}
return flow;
}
inline int dinic(int s, int t) {
int ans = 0;
while (bfs(s, t))
ans += dfs(s, t, inf);
return ans;
}
int main() {
tot = -1;
memset(point, -1, sizeof(point));
memset(nxt, -1, sizeof(nxt));
m = getnum(); n = getnum();
for (int i = 1; i <= m; i++) {
int x = getnum();
int y = getnum();
int cap = getnum();
addedge(x, y, cap);
}
cout << dinic(1, n) << endl;
}
ISAP算法
// Codevs 1993
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
using namespace std;
const int max_n = 220;
const int max_m = 220;
const int max_e = max_m * 2;
const int inf = 1e9;
int point[max_n], nxt[max_e], v[max_e], remain[max_e], tot;
int deep[max_n], num[max_n], cur[max_n], lastedge[max_n];
bool vis[max_n];
int n, m;
inline int getnum() {
char c; int ans = 0;
while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
ans = c - '0';
while (isdigit(c = getchar())) ans = ans * 10 + c - '0';
return ans;
}
inline void addedge(int x, int y, int cap) {
tot++; nxt[tot] = point[x]; point[x] = tot; v[tot] = y; remain[tot] = cap;
tot++; nxt[tot] = point[y]; point[y] = tot; v[tot] = x; remain[tot] = 0;
}
inline int addflow(int s, int t) {
int ans = inf, now = t;
while (now != s) {
ans = min(ans, remain[lastedge[now]]);
now = v[lastedge[now] ^ 1];
}
now = t;
while (now != s) {
remain[lastedge[now]] -= ans;
remain[lastedge[now] ^ 1] += ans;
now = v[lastedge[now] ^ 1];
}
return ans;
}
inline void bfs(int t) {
for (int i = 1; i <= n; i++)
deep[i] = n;
memset(vis, 0, sizeof(vis));
queue<int> q;
deep[t] = 0;
q.push(t); vis[t] = true;
while (!q.empty()) {
int now = q.front(); q.pop();
for (int tmp = point[now]; tmp != -1; tmp = nxt[tmp])
if (!vis[v[tmp]] && remain[tmp ^ 1]) {
vis[v[tmp]] = true;
deep[v[tmp]] = deep[now] + 1;
q.push(v[tmp]);
}
}
}
inline int isap(int s, int t) {
int ans = 0, now = s;
bfs(t);
for (int i = 1; i <= n; i++) num[deep[i]]++;
for (int i = 1; i <= n; i++) cur[i] = point[i];
while (deep[s] < n) {
if (now == t) {
ans += addflow(s, t);
now = s;
}
bool has_find = false;
for (int tmp = cur[now]; tmp != -1; tmp = nxt[tmp]) {
int u = v[tmp];
if (deep[u] + 1 == deep[now] && remain[tmp]) {
has_find = true;
cur[now] = tmp;
lastedge[u] = tmp;
now = u;
break;
}
}
if (!has_find) {
int minn = n - 1;
for (int tmp = point[now]; tmp != -1; tmp = nxt[tmp])
if (remain[tmp])
minn = min(minn, deep[v[tmp]]);
if (!(--num[deep[now]])) break;
num[deep[now] = minn + 1]++;
cur[now] = point[now];
if (now != s)
now = v[lastedge[now] ^ 1];
}
}
return ans;
}
int main() {
tot = -1;
memset(point, -1, sizeof(point));
memset(nxt, -1, sizeof(nxt));
m = getnum(); n = getnum();
for (int i = 1; i <= m; i++) {
int x = getnum();
int y = getnum();
int cap = getnum();
addedge(x, y, cap);
}
cout << isap(1, n) << endl;
}
最小费用最大流