POJ 2112 挤牛奶 floyd+最大流+二分

题意:

有k个挤奶器,c头牛..每个挤奶器和每头牛之间都有特定的距离..k个挤奶器的位置用1~k的编号表示..奶牛的位置用k+1~k+c表示

每个挤奶器每天最多为m头牛挤奶..

求安排每头牛到挤奶器前的最大距离的最小值..

思路:

先用floyd求出每头牛到每台挤奶器的最短距离..

然后用二分判断最大距离最小值是多少..

check()函数就是根据按距离建图后这个网络流的最大流==牛的头数

其中建图先建一个超级源点..作为每头牛的前驱..他们的流量为1..

然后建一个超级汇点..作为每台挤奶器的后继..他们的流量为m..

如果由floyd求出的最短距离 >= 二分假设的最大距离最小值x..就连线..然后根据这个求出的图来求最大流..

Tips:

※ 要注意全局变量和局部变量不要冲撞..

※ 求最大流算法很多..EK/Dicnic..还有..%&@^%$%

※ 这道题还可以用二分图的多重匹配来完成..<没做>

Code:

<EK>
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 #define INF 0x1f1f1f1f
 6 #define clr(x) memset(x, 0, sizeof(x))
 7 
 8 int G[250][250], K, c, m, n;
 9 int arr[250][250];
10 int dis[250][250];
11 int flow[250][250], a[250], f, p[250];
12 
13 
14 void init(int x)
15 {
16     int i, j, k;
17     clr(G);
18     for(i = 1; i <= K; ++i)
19     G[i][n+1] = m;
20     for(i = K+1; i <= n; ++i)
21     G[0][i] = 1;
22 
23     for(i = K+1; i <= n; ++i)
24     for(j = 1; j <= K; ++j){
25         if(arr[i][j] && arr[i][j] <= x) G[i][j] = 1;
26     }
27 }
28 
29 int EK(int s, int t)
30 {
31     clr(flow);
32     clr(p);
33     queue<int> q;
34     int f = 0;
35     while(1)
36     {
37         clr(a);
38         a[s] = INF;
39         q.push(s);
40         while(!q.empty())
41         {
42             int u = q.front();
43             q.pop();
44             for(int v = 0; v <= n+1; ++v)
45             if(!a[v] && G[u][v] > flow[u][v])
46             {
47                 p[v] = u;
48                 q.push(v);
49                 a[v] = a[u] < G[u][v] - flow[u][v]?a[u]:G[u][v]-flow[u][v];
50             }
51         }
52         if(a[t] == 0) break;
53         for(int u = t; u != s; u = p[u]){
54             flow[p[u]][u] += a[t];
55             flow[u][p[u]] -= a[t];
56         }
57         f += a[t];
58 
59     }
60     return f;
61 }
62 
63 int main()
64 {
65     int i, j, k;
66     while(scanf("%d %d %d", &K, &c, &m) != EOF)
67     {
68         clr(arr);
69         n = K+c;
70         for(i = 1; i <= n; ++i)
71         for(j = 1; j <= n; ++j)
72         scanf("%d", &arr[i][j]);
73 
74         for(k = 1; k <= n; ++k)
75         for(i = 1; i <= n; ++i){
76             if(arr[i][k])
77             for(j = 1; j <= n; ++j){
78                 if(arr[k][j] && (arr[i][k] + arr[k][j] < arr[i][j] || arr[i][j] == 0))
79                 arr[i][j] = arr[i][k]+arr[k][j];
80             }
81         }
82         int low, top, mid;
83         low = top = 0;
84         for(i = K+1; i <= n; ++i)
85         for(j = 1; j <= K; ++j)
86         if(arr[i][j] > top) top = arr[i][j];
87 
88         int tmp;
89         while(low < top)
90         {
91             mid = (low+top)/2;
92             init(mid);
93             tmp = EK(0, n+1);
94             if(tmp != c) low = mid+1;
95             else top = mid;
96         }
97         printf("%d\n", low);
98     }
99 }

 

<Dicnic>
 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <cstring>
 4 using namespace std;
 5 #define INF 100000
 6 #define MAX 300
 7 
 8 int G[MAX][MAX];
 9 int map[MAX][MAX];
10 bool sign[MAX][MAX];
11 bool used[MAX];
12 int K, c, n, m;
13 
14 void bg(int x)
15 {
16     int i, j;
17     memset(map, 0, sizeof(map));
18 
19     for(i = K+1; i <= n; ++i)
20     map[0][i] = 1;
21     for(i = 1; i <= K; ++i)
22     map[i][n+1] = m;
23 
24     for(i = K+1; i <= n; ++i)
25     for(j = 1; j <= K; ++j)
26     if(G[i][j] <= x) map[i][j] = 1;
27 }
28 
29 bool bfs()
30 {
31     memset(used, 0, sizeof(used));
32     memset(sign, 0, sizeof(sign));
33     int queue[100*MAX] = {0};
34     queue[0] = 0;
35     used[0] = 1;
36     int t = 1, f = 0;
37     while(f < t)
38     {
39         for(int i = 0; i <= n+1; ++i)
40         if(!used[i] && map[queue[f]][i]){
41             queue[t++] = i;
42             used[i] = 1;
43             sign[queue[f]][i] = 1;
44         }
45         f++;
46     }
47     if(used[n+1]) return true;
48     else return false;
49 }
50 
51 int dfs(int v, int sum)
52 {
53     int i, s, t;
54     if( v == n+1) return sum;
55     s = sum;
56     for(i = 0; i <= n+1; ++i){
57         if(sign[v][i]){
58             t = dfs(i, min(map[v][i], sum));
59             map[v][i] -= t;
60             map[i][v] += t;
61             sum -= t;
62         }
63     }
64     return s-sum;
65 }
66 
67 int main()
68 {
69     int i, j, k, l, r, mid, ans;
70     scanf("%d %d %d", &K, &c, &m);
71     n = K+c;
72     for(i = 1; i <= n; ++i)
73     for(j = 1; j <= n; ++j){
74         scanf("%d", &G[i][j]);
75         if(G[i][j] == 0) G[i][j] = INF;
76     }
77 
78     for(k = 1; k <= n; ++k)
79     for(i = 1; i <= n; ++i){
80         if(G[i][k] != INF)
81         for(j = 1; j <= n; ++j)
82         G[i][j] = min(G[i][j], G[i][k]+G[k][j]);
83     }
84 
85     l = 0, r = 10000;
86     while(l < r)
87     {
88         mid = (l+r)/2;
89         ans = 0;
90         bg(mid);
91         while(bfs()) ans += dfs(0, INF);
92         if(ans >= c) r = mid;
93         else l = mid+1;
94     }
95     printf("%d\n", r);
96     return 0;
97 }

 

 

posted @ 2012-08-06 16:49  Griselda.  阅读(445)  评论(0编辑  收藏  举报