一、多源汇最大流
1.1问题描述
给定一个包含n个点m条边的有向图,并给定每条边的容量,边的容量非负。其中有Sc个源点,Tc个汇点。图中可能存在重边和自环。求整个网络的最大流。
1.2思路分析
图论学习到网络流阶段,对于这个问题应该不难想到是建立虚拟源汇点,连边,求最大流即可。
正确性证明:
对于原图可行流,叠加到新图上,对于除ST外的点和边自然满足可行流的限制,对于S,T的相关边由于容量都是正无穷,所以自然也满足可行流的限制
对于新图的可行流,对于除ST外的点都满足流量守恒,新图所有边都满足容量限制,那么撤去S、T和相关边后自然得到了原图的可行流。
所以原图可行流和新图可行流是双射关系,那么新图最大流自然是原图最大流
1.3算法实现
- 建立虚拟源点S,虚拟汇点T,S和所有源点si建立容量为正无穷的边,所有汇点ti和T建立容量为正无穷的边
- 跑dinic算法
1.4OJ练习
多源汇最大流 POJ1459 – Power Network (poj.org)
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
#define sc scanf
const int N = 105, M = (10010 + N * 2) << 1, inf = 1e9;
int head[N], idx, cur[N], d[N], s, t, ns, nt, n, m;
struct edge
{
int v, c, nxt;
} edges[M];
void addedge(int u, int v, int c)
{
edges[idx].v = v, edges[idx].c = c, edges[idx].nxt = head[u],
head[u] = idx++;
}
void add(int u, int v, int c)
{
addedge(u, v, c), addedge(v, u, 0);
}
int dfs(int u, int limit)
{
if (u == t)
return limit;
int res = 0;
for (int i = cur[u]; ~i && limit; i = edges[i].nxt)
{
cur[u] = i;
int v = edges[i].v;
if (d[v] == d[u] + 1 && edges[i].c)
{
int incf = dfs(v, min(edges[i].c, limit));
if (!incf)
d[v] = 0;
res += incf, edges[i].c -= incf, edges[i ^ 1].c += incf, limit -= incf;
}
}
return res;
}
bool bfs()
{
memset(d, 0, sizeof(d));
queue<int> q;
q.push(s), d[s] = 1;
while (q.size())
{
int u = q.front();
q.pop();
for (int i = head[u]; ~i; i = edges[i].nxt)
{
int v = edges[i].v;
if (!d[v] && edges[i].c)
{
d[v] = d[u] + 1, q.push(v);
if (v == t)
return true;
}
}
}
return false;
}
int dinic()
{
int res = 0;
while (bfs())
memcpy(cur, head, sizeof(head)), res += dfs(s, inf);
return res;
}
void solve()
{
while (~sc("%lld%lld%lld%lld", &n, &ns, &nt, &m))
{
memset(head, -1, sizeof(head)), idx = 0, s = 0, t = n + 1;
for (int i = 0, a, b, c; i < m; i++)
{
while (getchar() != '(')
;
sc("%lld,%lld)%lld", &a, &b, &c), add(a + 1, b + 1, c);
}
for (int i = 0, a, b; i < ns; i++)
{
while (getchar() != '(')
;
sc("%lld)%lld", &a, &b), add(s, a + 1, b);
}
for (int i = 0, a, b; i < nt; i++)
{
while (getchar() != '(')
;
sc("%lld)%lld", &a, &b), add(a + 1, t, b);
}
printf("%lld\n", dinic());
}
}
signed main()
{
// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
// freopen("in.txt", "r", stdin);
int _ = 1;
// cin >> _;
while (_--)
solve();
return 0;
}