Codeforces 546 E:士兵的旅行 最大网络流
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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。