spfa写挂一次
n,m看反一次
数组开小一次
233333333
丧心病狂的拆点技能get
顺便YM faebdc
Code:
#include <cstdio>
#include <cstring>
#include <queue>
#include <bitset>
using namespace std;
#define INF 0x7FFFFFFF
queue<int> Q;
#define N (60*9+60+2+233)
#define M (60*60*9+233)
bitset<N> vis;
struct E
{
int to, f, next, op, c;
}G[M<<2];
int bh[61][10], point[N], S, T, cnt, D[N], n, m, pre[N], t[61][10], path[N], res;
inline void add(int u, int v, int f, int F, int c)
{
cnt++, G[cnt] = (E){v, f, point[u], cnt+1, c}, point[u] = cnt;
cnt++, G[cnt] = (E){u, F, point[v], cnt-1, -c}, point[v] = cnt;
}
inline bool spfa()
{
int u, v;
for (u = S;u <= T; ++u)
D[u] = INF;
while (!Q.empty())Q.pop();
Q.push(S);
vis.reset();
D[S] = 0;
pre[S] = -1;
vis[S] = 1;
while (!Q.empty())
{
u = Q.front(), Q.pop();
for (int e = point[u];e;e = G[e].next)
{
v = G[e].to;
if (G[e].f > 0 && D[u] + G[e].c < D[v])
{
D[v] = D[u] + G[e].c;
pre[v] = u;
path[v] = e;
if (!vis[v])
vis[v] = 1, Q.push(v);
}
}
vis[u] = 0;
}
return D[T] != INF;
}
inline int argument()
{
int i, delta = INF, flow = 0;
for (i = T;pre[i] != -1;i = pre[i])
{
int e = path[i];
delta = min(G[e].f, delta);
}
for (i = T;pre[i] != -1;i = pre[i])
{
int e = path[i];
G[e].f -= delta;
G[G[e].op].f += delta;
flow += G[e].c * delta;
}
return flow;
}
int main()
{
int i, j, k;
scanf("%d %d", &m, &n);
S = 0, T = n+n*m+1;
for (i = 1;i <= n; ++i)
for (j = 1;j <= m; ++j)
{
scanf("%d", &t[i][j]);
bh[i][j] = (i-1)*m+j+n;
}
for (i = 1;i <= n; ++i)
{
add(S, i, 1, 0, 0);
for (j = 1;j <= m; ++j)
for (k = 1;k <= n; ++k)
add(i, bh[k][j], 1, 0, t[i][j]*k);
}
for (i = 1;i <= n; ++i)
for (j = 1;j <= m; ++j)
add(bh[i][j], T, 1, 0, 0);
while (spfa())res += argument();
printf("%.2lf\n", (double)res/(double)n);
return 0;
}