Optimal Milking POJ-2112

题意:

有C头奶牛和K台挤奶机,已知每台挤奶机只能给M头牛挤奶。奶牛编号从K+1 到 K+C,挤奶机编号从1 到 K。现在给你一个 (K + C) * (K + C)的矩阵,矩阵第 i 行 第 j 列 的元素代表第i个点到第j个点的距离。求给每头奶牛挤奶的,使得C头奶牛需要行走的路程中的最大路程的最小值。

思路:

Floyd求每头奶牛到挤奶机的最小距离,二分答案,每次 check 对于距离小于 mid 的 i ,j 建边,判断最大流是否等于奶牛数。

代码

  1 //#include<bits/stdc++.h>
  2 #include <set>
  3 #include <map>
  4 #include <stack>
  5 #include <cmath>
  6 #include <queue>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 
 14 #define ll long long
 15 #define pll pair<ll,ll>
 16 #define pii pair<int,int>
 17 #define bug printf("*********\n")
 18 #define FIN freopen("input.txt","r",stdin);
 19 #define FON freopen("output.txt","w+",stdout);
 20 #define IO ios::sync_with_stdio(false),cin.tie(0)
 21 #define ls root<<1
 22 #define rs root<<1|1
 23 #define Q(a) cout<<a<<endl
 24 
 25 using namespace std;
 26 const int inf = 0x3f3f3f3f;
 27 const ll Inf = 1e18 + 7;
 28 const int maxn = 1e5 + 5;
 29 const int mod = 1e9 + 7;
 30 
 31 ll gcd(ll a, ll b)
 32 {
 33     return b ? gcd(b, a % b) : a;
 34 }
 35 
 36 ll lcm(ll a, ll b)
 37 {
 38     return a / gcd(a, b) * b;
 39 }
 40 
 41 ll read()
 42 {
 43     ll p = 0, sum = 0;
 44     char ch;
 45     ch = getchar();
 46     while (1)
 47     {
 48         if (ch == '-' || (ch >= '0' && ch <= '9'))
 49             break;
 50         ch = getchar();
 51     }
 52 
 53     if (ch == '-')
 54     {
 55         p = 1;
 56         ch = getchar();
 57     }
 58     while (ch >= '0' && ch <= '9')
 59     {
 60         sum = sum * 10 + ch - '0';
 61         ch = getchar();
 62     }
 63     return p ? -sum : sum;
 64 }
 65 
 66 struct Dinic
 67 {
 68     int head[maxn], tot, cur[maxn];
 69     int dis[maxn];
 70     int s, e;
 71     queue<int>q;
 72 
 73     struct node
 74     {
 75         int v, w;
 76         int next;
 77     }p[maxn];
 78 
 79     void init()
 80     {
 81         tot = 0;
 82         memset(head, -1, sizeof head);
 83     }
 84 
 85     void add(int u, int v, int w)
 86     {
 87         p[tot].v = v;
 88         p[tot].w = w;
 89         p[tot].next = head[u];
 90         head[u] = tot++;
 91     }
 92 
 93     void addEdge(int u, int v, int w)
 94     {
 95         add(u, v, w);
 96         add(v, u, 0);
 97     }
 98 
 99     bool bfs()
100     {
101         memset(dis, 0, sizeof dis);
102         while (!q.empty())   q.pop();
103         dis[s] = 1;
104         q.push(s);
105         while (!q.empty())
106         {
107             int x = q.front();
108             q.pop();
109             for (int i = head[x]; i != -1; i = p[i].next)
110             {
111                 int v = p[i].v, w = p[i].w;
112                 if (!dis[v] && w)
113                 {
114                     dis[v] = dis[x] + 1;
115                     q.push(v);
116                 }
117             }
118         }
119         if (dis[e])  return true;
120         return false;
121     }
122 
123     int dfs(int x, int W)
124     {
125         if (x == e || W == 0)  return W;
126         int res = 0;
127         for (int i = cur[x]; i != -1; i = p[i].next)
128         {
129             cur[x] = p[i].next;
130             int v = p[i].v, w = p[i].w;
131             if (dis[v] == dis[x] + 1)
132             {
133                 int f = dfs(v, min(w, W));
134                 p[i].w -= f;
135                 p[i ^ 1].w += f;
136                 W -= f;
137                 res += f;
138                 if (W == 0)    break;
139             }
140         }
141         return res;
142     }
143 
144     int getMaxFlow()
145     {
146         int ans = 0;
147         while (bfs())
148         {
149             for (int i = s; i <= e; ++i) cur[i] = head[i];
150             ans += dfs(s, inf);
151         }
152         return ans;
153     }
154 }DC;
155 
156 struct stortest_Floyd {
157     int a[5000][5000];
158     void floyd(int num) {
159         for (int k = 1; k <= num; k++) {
160             for (int i = 1; i <= num; i++) {
161                 for (int j = 1; j <= num; j++) {
162                     if (a[i][j] > a[i][k] + a[k][j]) {
163                         a[i][j] = a[i][k] + a[k][j];
164                     }
165                 }
166             }
167         }
168     }
169 }Floyd;
170 
171 int k, c, m;
172 int num;
173 
174 void add(int x)
175 {
176     for (int i = 1; i <= k; ++i)
177     {
178         for (int j = k + 1; j <= num; ++j)
179         {
180             if (Floyd.a[i][j] <= x)
181                 DC.addEdge(j, i, 1);
182         }
183     }
184     for (int i = 1; i <= k; ++i)
185     {
186         DC.addEdge(i, DC.e, m);
187     }
188     for (int i = k + 1; i <= num; ++i)
189     {
190         DC.addEdge(DC.s, i, 1);
191     }
192 }
193 
194 int main()
195 {
196     while (~scanf("%d %d %d", &k, &c, &m))
197     {
198         num = k + c;
199         DC.s = 0, DC.e = num + 1;
200         int nv = num + 2;
201 
202         for (int i = 1; i <= num; ++i)
203         {
204             for (int j = 1; j <= num; ++j)
205             {
206                 scanf("%d", &Floyd.a[i][j]);
207                 if (i != j && !Floyd.a[i][j])
208                 {
209                     Floyd.a[i][j] = inf;
210                 }
211             }
212         }
213         Floyd.floyd(num);
214 
215         int l = 0, r = inf;
216         int ans = 0;
217         while (l <= r)
218         {
219             int mid = (l + r) / 2;
220             DC.init();
221             add(mid);
222             int res = DC.getMaxFlow();
223             if (res == c)
224             {
225                 ans = mid;
226                 r = mid - 1;
227             }
228             else l = mid + 1;
229         }
230         printf("%d\n", ans);
231     }
232 }

猜你喜欢

转载自www.cnblogs.com/zhang-Kelly/p/12593195.html