题意:有n个银行m个警察,给出每个警察到每个银行花费的时间,问最小花费时间平均是多少。
题解:直接建图+最大流最小费模板。
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
const int N = 100;
const int INF = 0x3f3f3f3f;
int n, m, p[N];
int cap[N][N], flow[N][N], maxflow;
double d[N], cost[N][N], c;
double ek(int scr, int en) {
queue<int> q;
memset(flow, 0, sizeof(flow));
maxflow = c = 0;
while (1) {
bool vis[N];
memset(vis, 0, sizeof(vis));
for (int i = 0; i <= en; i++)
d[i] = INF;
d[scr] = 0;
q.push(scr);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for (int v = 0; v <= en; v++) {
if (cap[u][v] > flow[u][v] && d[v] > d[u] + cost[u][v]) {
d[v] = d[u] + cost[u][v];
p[v] = u;
if (!vis[v]) {
vis[v] = true;
q.push(v);
}
}
}
}
if (d[en] == INF)
break;
int a = INF;
for (int u = en; u != scr; u = p[u])
a = a < cap[p[u]][u] - flow[p[u]][u] ? a : cap[p[u]][u] - flow[p[u]][u];
for (int u = en; u != scr; u = p[u]) {
flow[p[u]][u] += a;
flow[u][p[u]] -= a;
}
c += d[en] * a;
maxflow += a;
}
return c;
}
int main() {
while (scanf("%d%d", &n, &m) && m + n) {
memset(cap, 0, sizeof(cap));
double b;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
scanf("%lf", &b);
cap[j][m + i] = 1;
cost[j][m + i] = b;
cost[m + i][j] = -b;
}
for (int i = 1; i <= m; i++)
cap[0][i] = 1;
for (int i = 1; i <= n; i++)
cap[i + m][n + m + 1] = 1;
printf("%.2lf\n", ek(0, n + m + 1) / n + 1e-9);
}
return 0;
}