二次联通门 : BZOJ 1070: [SCOI2007]修车
/* BZOJ 1070: [SCOI2007]修车 费用流 i,j写反,调了一下午 lqz已经废了 */ #include <cstdio> #include <iostream> #define rg register inline void read (int &n) { rg char c = getchar (); for (n = 0; !isdigit (c); c = getchar ()); for (; isdigit (c); n = n * 10 + c - '0', c = getchar ()); } int S, T; #define Max 7000 #define INF 1e9 namespace net { const int MaxE = 200000; int _n[MaxE], _v[MaxE], list[Max], _f[MaxE], _c[MaxE], EC = 1, d[Max], q[MaxE], pre[Max]; bool is[Max]; int c[Max]; inline void In (int u, int v, int f, int c) { _v[++ EC] = v, _n[EC] = list[u], list[u] = EC, _f[EC] = f, _c[EC] = c; _v[++ EC] = u, _n[EC] = list[v], list[v] = EC, _f[EC] = 0, _c[EC] = -c; } bool Bfs () { int h = 1, t = 1; q[t] = S; rg int i, n; for (i = 0; i <= T; ++ i) d[i] = INF, is[i] = false; for (d[S] = 0, c[S] = INF, pre[S] = 0; h <= t; ++ h) for (n = q[h], is[n] = false, i = list[n]; i; i = _n[i]) if (d[_v[i]] > d[n] + _c[i] && _f[i]) { d[_v[i]] = d[n] + _c[i], pre[_v[i]] = i, c[_v[i]] = std :: min (c[n], _f[i]); if (!is[_v[i]]) q[++ t] = _v[i], is[_v[i]] = true; } return d[T] < INF; } int Do () { int res = 0; rg int i; for (int x; Bfs (); ) { for (x = c[T], i = T; i != S; i = _v[pre[i] ^ 1]) _f[pre[i]] -= x, _f[pre[i] ^ 1] += x; res += d[T] * x; } return res; } } int a[Max / 100][Max / 100]; int main (int argc, char *argv[]) { int N, M; read (M), read (N); rg int i, j, k; S = 0, T = N * M * 2; for (i = 1; i <= N; ++ i) for (j = 1; j <= M; ++ j) read (a[j][i]); for (i = 1; i <= M; ++ i) for (j = 1; j <= N; ++ j) net :: In ((i - 1) * N + j, T, 1, 0); for (i = 1; i <= N; ++ i) net :: In (S, N * M + i, 1, 0); for (i = 1; i <= N; ++ i) for (j = 1; j <= M; ++ j) for (k = 1; k <= N; ++ k) net :: In (N * M + i, (j - 1) * N + k, 1, k * a[j][i]); int res = net :: Do (); printf ("%.2lf", (double) res / N); return 0; }