Loading

POJ 3686:The Windy's(最小费用最大流)***

http://poj.org/problem?id=3686

题意:给出n个玩具和m个工厂,每个工厂加工每个玩具有一个时间,问要加工完这n个玩具最少需要等待的平均时间。例如加工1号玩具时间为t1,加工2号玩具时间为t2。那么先加工玩具1再加工玩具2花费的时间是t1+(t1+t2),先加工玩具2在加工玩具1花费的时间是t2+(t1+t2)。

思路:假设所有玩具在一个工厂加工,那么等待的时间是

t1 + (t1 + t2) + (t1 + t2 + t3) + ……

= t1 * n + t2 * (n-1) + t3 * (n-2) + ……

那么可以把每个工厂能够加工n个玩具转化成有n个工厂每个只能够加工一个玩具,即每个工厂被划分成权值w为1,2,3,……,n的工厂,然后每个工厂制造某个玩具花费的时间为权值*本来需要的时间。

建图即:

源点向每个玩具连流量为1,费用为0的边,

每个玩具向每个工厂连流量为1,费用为w(w为工厂的权值)*cost的边,

每个工厂向源点连流量为1,费用为0的边。

然后跑一遍最小费用最大流,最后把答案除以玩具数就是最终答案。

这个建图思维很厉害。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 using namespace std;
 6 #define N 2666
 7 #define INF 0x3f3f3f3f
 8 struct Edge {
 9     int u, v, nxt, cap, cost;
10     Edge () {}
11     Edge (int u, int v, int nxt, int cap, int cost) : u(u), v(v), nxt(nxt), cap(cap), cost(cost) {}
12 } edge[N*N];
13 int n, m, mp[55][55], head[N], tot, pre[N], dis[N], vis[N], S, T;
14 
15 void Add(int u, int v, int cap, int cost) {
16     edge[tot] = Edge(u, v, head[u], cap, cost); head[u] = tot++;
17     edge[tot] = Edge(v, u, head[v], 0, -cost); head[v] = tot++;
18 }
19 
20 bool SPFA(int S, int T) {
21     queue<int> que; que.push(S);
22     memset(dis, INF, sizeof(dis));
23     memset(vis, 0, sizeof(vis));
24     dis[S] = 0, vis[S] = 1;
25     while(!que.empty()) {
26         int u = que.front(); que.pop();
27         vis[u] = 0; // 忘了这句.WA了N久
28         for(int i = head[u]; ~i; i = edge[i].nxt) {
29             int v = edge[i].v, cap = edge[i].cap, cost = edge[i].cost;
30             if(dis[v] > dis[u] + cost && cap > 0) {
31                 dis[v] = dis[u] + cost; pre[v] = i;
32                 if(!vis[v]) vis[v] = 1, que.push(v);
33             }
34         }
35     }
36     return dis[T] < INF;
37 }
38 
39 double MFMC(int S, int T) {
40     int u, flow;
41     double ans = 0;
42     while(SPFA(S, T)) {
43         u = T, flow = INF;
44         while(u != S) {
45             if(flow > edge[pre[u]].cap) flow = edge[pre[u]].cap;
46             u = edge[pre[u]].u;
47         } u = T;
48         while(u != S) {
49             edge[pre[u]].cap -= flow, edge[pre[u]^1].cap += flow;
50             ans += edge[pre[u]].cost * flow;
51             u = edge[pre[u]].u;
52         }
53     }
54     return ans;
55 }
56 
57 int main() {
58     int t; scanf("%d", &t);
59     while(t--) {
60         scanf("%d%d", &n, &m);
61         for(int i = 1; i <= n; i++)
62             for(int j = 1; j <= m; j++)
63                 scanf("%d", &mp[i][j]);
64         S = 0, T = n * m + n + 1;
65         memset(head, -1, sizeof(head)); tot = 0;
66         for(int i = 1; i <= n; i++) {
67             Add(S, i, 1, 0);
68             for(int j = 1; j <= m; j++) {
69                 Add(j * n + i, T, 1, 0);
70                 for(int k = 1; k <= n; k++) {
71                     Add(i, j * n + k, 1, k * mp[i][j]);
72                 }
73             }
74         }
75         printf("%.6f\n", MFMC(S, T) / n);
76     }
77     return 0;
78 }

 

posted @ 2017-04-23 09:43  Shadowdsp  阅读(174)  评论(0编辑  收藏  举报