题目链接:UVa 10330 Power Transmission
最大流 + 拆点。
把题目中说了每个点有容量限制,那么我们把每个点拆成两个点i和i + n(拆法应该有多种),把cap[i][i + n]设为这个点的容量,然后就跟普通的最大流问题一样了。
原点s = 0,汇点t = 2 * n + 1,要把 cap[0][k]和cap[k + n][t] 设为INF,表示这几段的流量是无限制的。
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
const int MAX_N = 200 + 20;
const int INF = (1 << 30);
int cap[MAX_N][MAX_N], flow[MAX_N][MAX_N], p[MAX_N];
int n, m, s, t, _cap;
void init()
{
memset(flow,0,sizeof(flow));
memset(cap,0,sizeof(cap));
s = 0;
t = 2 * n + 1;
for(int i = 1; i <= n; i++)
{
cin >> _cap;
cap[i][i + n] += _cap;
}
cin >> m;
int a, b;
for(int i = 1; i <= m; i++)
{
cin >> a >> b >> _cap;
cap[a + n][b] += _cap;
}
cin >> a >> b;
int k;
for(int i = 1; i <= a; i++)
{
cin >> k;
cap[0][k] += INF;
}
for(int i = 1; i <= b;i++)
{
cin >> k;
cap[k + n][t] += INF;
}
}
int maxFlow()
{
queue<int> q;
int ans = 0, a[MAX_N];
while(true)
{
q.push(s);
memset(a, 0, sizeof(a));
a[s] = INF;
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = 0; i <= t; i++)
{
if (!a[i] && cap[u][i] > flow[u][i])
{
p[i] = u;
q.push(i);
a[i] = min(a[u],cap[u][i] - flow[u][i]);
}
}
}
if (a[t] == 0)
break;
for (int i = t;i != s;i = p[i])
{
flow[p[i]][i] += a[t];
flow[i][p[i]] -= a[t];
}
ans += a[t];
}
return ans;
}
int main()
{
while(cin >> n)
{
init();
cout << maxFlow() << endl;
}
return 0;
}