uva 10746 - Crime Wave - The Sequel(费用流)

题目链接:uva 10746 - Crime Wave - The Sequel


题目大意:自从银行被抢之后,警局为每个银行都安排了一个警察,现在有n个银行和m警察,给出每个警察到达各个银行的时间,问说怎么样安排人手,可以使的警察到达银行的平均时间最小。


解题思路:网络流的最小费用最大流,起点s与m个警察相连,容量为1,费用为0;n个银行与汇点t相连,容量为1,费用为0;然后就是警察和银行之间的边,为有向边,警察指向银行,费用为时间。然后建好图就是单纯的费用流问题。


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
#include <vector>

using namespace std;

#define min(a,b) (a)<(b)?(a):(b)

const int N = 205;
const int T = 100;
const int INF = 1 << 30;

int n, m, tmp, g[N][N], f[N][N];
double cost[N][N];
vector<int> v[N];

void add(int x,  int y) {
	g[x][y]++;
	v[x].push_back(y);
	v[y].push_back(x);
}

void init() {

	tmp = 200;
	memset(g, 0, sizeof(g));
	memset(f, 0, sizeof(f));
	memset(cost, 0, sizeof(cost));
	for (int i = 0; i < N; i++)
		v[i].clear();

	for (int i = 1; i <= n; i++) {

		add(0, i + T);
		add(i + T, i);
		for (int j = 1; j <= m; j++) {
			add(i, j + n + T);
		}
	}

	for (int i = 1; i <= m; i++) {
		add(i + n + T, i + n);
		add(i + n, tmp);
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			scanf("%lf", &cost[i][j + n + T]);
			cost[j + n + T][i] = -cost[i][j + n + T];
		}
	}
}

void solve() {
	queue<int> que;
	double ans = 0, d[N];
	int c, flow = 0,  path[N], vis[N];

	while (1) {

		for (int i = 0; i <= tmp; i++)	
			d[i] = (i == 0) ? 0 : INF;
		memset(path, 0, sizeof(path));
		memset(vis, 0, sizeof(vis));
		que.push(0);
		vis[0] = 1;

		while (!que.empty() ) {
			c = que.front(), que.pop();
			vis[c] = 0;

			int top = v[c].size();
			for (int i = 0; i < top; i++) {
				if (g[c][v[c][i]] > f[c][v[c][i]] && d[v[c][i]] - d[c] - cost[c][v[c][i]] > 1e-6) {
					d[v[c][i]] = d[c] + cost[c][v[c][i]];
					path[v[c][i]] = c;

					if ( vis[v[c][i]] == 0) {
						que.push(v[c][i]);
						vis[v[c][i]] = 1;
					}
				}
			}
		}

		if (INF - d[tmp] < 1e-6) break;
		int t = INF;

		for (int i = tmp; i; i = path[i]) t = min(g[path[i]][i] - f[path[i]][i], t);

		flow += t;
		ans += t * d[tmp];

		for (int i = tmp; i; i= path[i]) {
			f[path[i]][i] += t;
			f[i][path[i]] -= t;
		}
	}
	printf("%.2lf\n", ans / n + 0.001);
}

int main () {
	while (scanf("%d%d", &n, &m), n + m) {
		init();
		solve();
	}
	return 0;
}


你可能感兴趣的:(uva 10746 - Crime Wave - The Sequel(费用流))