51nod上也有这道题,题意就是:
在某个国家有n个城市,他们通过m条无向的道路相连。每个城市有一支军队。第i个城市的军队有ai个士兵。现在士兵开始移动。每个士兵可以呆在原地,或者走到和他所在城市直接相邻的城市,即设每一条边长度为1的话,他离开之后不能距离原来城市大于1。
判断移动之后,能不能使得第i个城市恰好有bi个士兵。
(......)
发现题目一旦像这种有一堆点的起始状态,然后是目标状态的,并且可以用路径来更改每个点的状态的。这种题用最大网络流做准没错。1.将源点与各个点相连,容量就是a[i]。
2.将汇点与各个点相连,容量就是b[i]。
3.将a[i]与a[i+N]相连,容量是INF,表示士兵可以留在自己的城市里面。
4.对于两个城市i与j有边的,将i与j+N相连,将j与i+N相连,容量均为INF,表示士兵可以从这两个城市来回窜。
5.求一下最大流,保证最大流填满了源点的每一条管道,填满了汇点的每一条管道。即最大流等于a[i]之和,也等于b[i]之和,就是YES。否则就是NO。
代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <queue>
#pragma warning(disable:4996)
using namespace std;
const int sum = 205;
const int INF = 99999999;
int cap[sum][sum], flow[sum][sum], a[sum], p[sum];
int val[1005];
int flag[1005];
int sum1, sum2;
int N, M;
void Edmonds_Karp()
{
int u, t, result = 0;
queue <int> s;
while (s.size())s.pop();
while (1)
{
memset(a, 0, sizeof(a));
memset(p, 0, sizeof(p));
a[0] = INF;
s.push(0);
while (s.size())
{
u = s.front();
s.pop();
for (t = 0; t <= M + 1; t++)
{
if (!a[t] && flow[u][t]<cap[u][t])
{
s.push(t);
p[t] = u;
a[t] = min(a[u], cap[u][t] - flow[u][t]);//要和之前的那个点,逐一比较,到M时就是整个路径的最小残量
}
}
}
if (a[M + 1] == 0)
break;
result += a[M + 1];
for (u = M + 1; u != 0; u = p[u])
{
flow[p[u]][u] += a[M + 1];
flow[u][p[u]] -= a[M + 1];
}
}
if (sum1 == result&&sum2 == result)
{
cout << "YES" << endl;
int i, j;
for (i = 1; i <= M/2; i++)
{
for (j = 1; j <= M/2; j++)
{
if (j == 1)
{
cout << flow[i][j + M/2];
}
else
{
cout <<" "<<flow[i][j + M/2];
}
}
cout << endl;
}
}
else
{
cout << "NO" << endl;
}
}
int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout);
int i, temp, temp1, temp2;
cin >> N >> M;
sum1 = 0;
sum2 = 0;
memset(cap, 0, sizeof(cap));
for (i = 1; i <= N; i++)
{
cin >> temp;
cap[0][i] = temp;
sum1 += temp;
}
for (i = 1; i <= N; i++)
{
cin >> temp;
cap[i + N][2 * N + 1] = temp;
sum2 += temp;
cap[i][i + N] = INF;
}
for (i = 1; i <= M; i++)
{
cin >> temp1 >> temp2;
cap[temp1][temp2 + N] = INF;
cap[temp2][temp1 + N] = INF;
}
M = 2 * N ;
Edmonds_Karp();
//system("pause");
return 0;
}