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 }

 

 

你可能感兴趣的:(floyd)