Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
拆点后转变变为指派问题,然后用费用流求解(719ms)#include<cstdio> #include<climits> #include<queue> #include<cstring> #include<cmath> using namespace std; #define ll long long const int MAX_V = 2552; struct edge { int to, cap, cost, rev; edge(int t, int c, int co, int r): to(t), cap(c), cost(co), rev(r){} }; vector<edge> G[MAX_V]; int dist[MAX_V], prevv[MAX_V], preve[MAX_V], h[MAX_V], V, cost, flow, Z[51][51]; typedef pair<int, int> P; inline void add_edge(int from, int to, int cap, int cost) { G[from].push_back(edge(to, cap, cost, G[to].size())); G[to].push_back(edge(from, 0, -cost, G[from].size() - 1)); } void min_cost_flow(int s, int t) { memset(h, 0, sizeof(h)); cost = 0, flow = 0; for (;;) { priority_queue<P, vector<P>, greater<P> > que; que.push(P(0, s)); fill(dist, dist + MAX_V, INT_MAX); dist[s] = 0; for (int dis, v; !que.empty(); ) { v = que.top().second, dis = que.top().first; que.pop(); if (dis > dist[v]) continue; for (int i = 0; i < G[v].size(); ++i) { edge& e = G[v][i]; if (e.cap && dist[e.to] > dis + e.cost + h[v] - h[e.to]) { dist[e.to] = dis + e.cost + h[v] - h[e.to], prevv[e.to] = v, preve[e.to] = i; que.push(P(dist[e.to], e.to)); } } } if (dist[t] == INT_MAX) return; for (int v = 0; v <= V; ++v) h[v] += dist[v]; int d = INT_MAX; for (int v = t; v != s; v = prevv[v]) d = min(d, G[prevv[v]][preve[v]].cap); flow += d, cost += d * h[t]; for (int v = t; v != s; v = prevv[v]) { edge& e = G[prevv[v]][preve[v]]; e.cap -= d, G[v][e.rev].cap += d; } } } void solve() { int N, M, s = 0, t; scanf("%d%d", &N, &M); /* points: 0: s 1 ~ N: toys N * i + 1 ~ N * (i + 1): the i-th workshop N * (M + 1) + 1: t */ t = N + N * M + 1, V = t; for (int i = 0; i <= V; ++i) G[i].clear(); for (int i = 1; i <= N; ++i) for (int j = 1; j <= M; ++j) scanf("%d", &Z[i][j]); for (int i = 1; i <= N; ++i) add_edge(s, i, 1, 0); for (int j = 1; j <= M; ++j) { for (int k = 1; k <= N; ++k) { add_edge(N * j + k, t, 1, 0); for (int i = 1; i <= N; ++i) add_edge(i, N * j + k, 1, k * Z[i][j]); } } min_cost_flow(s, t); printf("%.6f\n", (double)cost / N); } int main() { int t; scanf("%d", &t); while (t--) solve(); return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator