POJ 2112 Optimal Milking (二分+最短路+最大流)

Posted 00isok

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2112 Optimal Milking (二分+最短路+最大流)相关的知识,希望对你有一定的参考价值。

<题目链接>

题目大意:

  有K台挤奶机和C头奶牛,都被视为物体,这K+C个物体之间存在路径。给出一个 (K+C)x(K+C) 的矩阵A,A[i][j]表示物体i和物体j之间的距离,有些物体之间可能没有直接通路。 每台挤奶机可以容纳m头奶牛去挤奶,且每个奶牛仅可以去往一台挤奶机。现在安排这C头奶牛去挤奶,每头奶牛会去往某个挤奶机,求出这C头奶牛去其挤奶的最长路径的最小值。

解题分析:
  因为要求最长路径的最小值,所以我们很容易想到二分答案。由于数据量较小,所以我们先用floyed求出所有点之间的最短距离,然后直接二分答案,枚举最长路径的最小值,再根据枚举的值建图,源点向所有机器连一条容量为m的边,所有的牛向汇点连一条容量为1的边,并且距离<=枚举值的机器与牛连一条容量为1的边,最后求最大流,如果最大流==c,则成立。

  1 #include <cstdio> 
  2 #include <cstring>
  3 #include <queue>
  4 #include <algorithm>
  5 #include <iostream>
  6 using namespace std;
  7 
  8 #define rep(i,s,t) for(int i=s;i<=t;i++)
  9 typedef long long LL;
 10 const int MX = 1050;
 11 const int MXE = 4 * MX * MX;
 12 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
 13 const int INF = 0x3f3f3f3f;
 14 int mp[250][250];
 15 int k, c, m,maxdist;
 16 struct MaxFlow {
 17     struct Edge {
 18         int v, nxt;
 19         LL w;
 20     } E[MXE];
 21     int tot, num, s, t;
 22     int head[MX];
 23     void init() {
 24         memset (head, -1, sizeof (head) );
 25         tot = 0;
 26     }
 27     void add (int u, int v, LL w) {
 28         E[tot].v=v,E[tot].nxt=head[u],E[tot].w=w;
 29         head[u] = tot++;
 30 
 31         E[tot].v=u,E[tot].nxt=head[v],E[tot].w=0;
 32         head[v] = tot++;
 33     }
 34     int  d[MX], vis[MX], gap[MX];
 35     void bfs() {
 36         memset (d, 0, sizeof (d) );
 37         memset (gap, 0, sizeof (gap) );
 38         memset (vis, 0, sizeof (vis) );
 39         queue<int>q;
 40         q.push (t);
 41         vis[t] = 1;
 42         while (!q.empty() ) {
 43             int u = q.front();
 44             q.pop();
 45             for (int i = head[u]; ~i; i = E[i].nxt) {
 46                 int v = E[i].v;
 47                 if (!vis[v]) {
 48                     d[v] = d[u] + 1;
 49                     gap[d[v]]++;
 50                     q.push (v);
 51                     vis[v] = 1;
 52                 }
 53             }
 54         }
 55     }
 56     int last[MX];
 57     LL dfs (int u, LL f) {
 58         if (u == t) return f;
 59         LL sap = 0;
 60         for (int i = last[u]; ~i; i = E[i].nxt) {
 61             int v = E[i].v;
 62             if (E[i].w > 0 && d[u] == d[v] + 1) {
 63                 last[u] = i;
 64                 LL tmp = dfs (v, min (f - sap, E[i].w) );
 65                 E[i].w -= tmp;
 66                 E[i ^ 1].w += tmp;
 67                 sap += tmp;
 68                 if (sap == f) return sap;
 69             }
 70         }
 71         if (d[s] >= num) return sap;
 72         if (! (--gap[d[u]]) ) d[s] = num;
 73         ++gap[++d[u]];
 74         last[u] = head[u];
 75         return sap;
 76     }
 77     LL solve (int st, int ed, int n) {
 78         LL flow = 0;
 79         num = n;s = st;t = ed;
 80         bfs();
 81         memcpy (last, head, sizeof (head) );
 82         while (d[s] < num) flow += dfs (s, INFLL);
 83         return flow;
 84     }
 85 }Maxflow;
 86 
 87 int MaxFlow_check(int mid) {    //建图,跑最大流
 88     Maxflow.init();    //初始化
 89     for (int i = 1 ; i <= k ; i++) {
 90         Maxflow.add(0, i, m);     //源点与机器相连,容量为m
 91         for (int j = k + 1 ; j <= k + c ; j++ )
 92             if (mp[i][j] <= mid) Maxflow.add(i, j, 1);     //机器与牛相连,容量为1
 93     }
 94     for (int i = k + 1 ; i <= k + c ; i++)
 95         Maxflow.add(i, k + c + 1, 1);      //牛与汇点相连,容量为1
 96     if ((int)(Maxflow.solve( 0, k + c + 1, k + c + 2)) == c) return 1;
 97     return 0;
 98 }
 99 void Floyed(int n){
100     rep(k,1,n) rep(i,1,n) rep(j,1,n){
101         mp[i][j]=min(mp[i][j],mp[i][k]+mp[k][j]);
102         maxdist=max(maxdist,mp[i][j]);     //找到最大的mp[i][j],为寻找二分的上界
103     }
104 }
105 int main() {
106     while(~scanf("%d%d%d", &k, &c, &m)) {
107         for (int i = 1 ; i <= k + c ; i++)
108             for (int j = 1 ; j <= k + c ; j++) {
109                 scanf("%d", &mp[i][j]);
110                 if (i != j && !mp[i][j]) mp[i][j] = INF;    //将0置为不可达
111             }
112         maxdist=-INF;Floyed(k+c);
113         int l = 0, r = maxdist ,ans = 0;
114         while(l <= r) {
115             int mid = (l + r) >> 1;
116             if (MaxFlow_check(mid))ans = mid,r = mid - 1;
117             else l = mid + 1;
118         }
119         printf("%d
", ans);
120     }
121     return 0;
122 }

 

 

2018-11-24

以上是关于POJ 2112 Optimal Milking (二分+最短路+最大流)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2112 Optimal Milking(二分+最大流)

POJ2112:Optimal Milking(Floyd+二分图多重匹配+二分)

●POJ poj 2112 Optimal Milking

Optimal Milking(POJ2112+二分+Dinic)

POJ_2112_Optimal Milking 这里有超级快的网络流板子

POJ 2112 Optimal Milking (二分+最短路+最大流)