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\n", ans);
120     }
121     return 0;
122 }

2018-11-24

原文地址:https://www.cnblogs.com/00isok/p/10012691.html

时间: 2024-11-13 04:29:06

POJ 2112 Optimal Milking (二分+最短路+最大流)的相关文章

POJ 2112 Optimal Milking 二分答案+最大流

首先二分最长的边,然后删去所有比当前枚举的值长的边,算最大流,看是否能满足所有的牛都能找到挤奶的地方 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include

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

题目大意: 在一个农场里面,有k个挤奶机,编号分别是 1..k,有c头奶牛,编号分别是k+1 .. k+c,每个挤奶机一天最让可以挤m头奶牛的奶,奶牛和挤奶机之间用邻接矩阵给出距离.求让所有奶牛都挤到 奶的情况下,走的最远的那头奶牛走的距离最小是多少. 数据保证有解. 算法讨论: 首先可以想到是二分,然后在选择流网络的时候,一开始选择的最小费用最大流,让二分的边权充当最小费用,但是这样跑发现每次二分的是我们要跑的答案,不可行.所以就改用最大流. 最大流肯定是在二分的情况下判定最大流是否等于c,即

POJ 2112 —— Optimal Milking 二分+Floyd+最大流

原题:http://poj.org/problem?id=2112 #include<cstdio> #include<cstring> #include<string> #include<queue> #include<vector> #include<algorithm> #define inf 0x3f3f3f3f using namespace std; const int maxn = 250; int dis[maxn][

POJ 2112 Optimal Milking 最优挤奶方案 Floyd算法+二分查找+最大流

题目链接:POJ 2112 Optimal Milking Optimal Milking Time Limit: 2000MS   Memory Limit: 30000K Total Submissions: 12446   Accepted: 4494 Case Time Limit: 1000MS Description FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among

POJ 2112 Optimal Milking (二分 + floyd + 网络流)

POJ 2112 Optimal Milking 链接:http://poj.org/problem?id=2112 题意:农场主John 将他的K(1≤K≤30)个挤奶器运到牧场,在那里有C(1≤C≤200)头奶牛,在奶牛和挤奶器之间有一组不同长度的路.K个挤奶器的位置用1-K的编号标明,奶牛的位置用K+1-K+C 的编号标明.每台挤奶器每天最多能为M(1≤M≤15)头奶牛挤奶.寻找一个方案,安排每头奶牛到某个挤奶器挤奶,并使得C 头奶牛需要走的所有路程中的最大路程最小.每个测试数据中至少有一

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

POJ 2112 Optimal Milking 题目链接 题意:给定一些机器和奶牛,在给定距离矩阵,(不在对角线上为0的值代表不可达),每个机器能容纳m个奶牛,问所有奶牛都能挤上奶,那么走的距离最大的奶牛的最小值是多少 思路:明显的二分+最大流,注意floyd求出的距离矩阵最大值可能不止200,所以二分的上限要注意 代码: #include <cstdio> #include <cstring> #include <queue> #include <algori

POJ 2112—— Optimal Milking——————【多重匹配、二分枚举答案、floyd预处理】

Optimal Milking Time Limit:2000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2112 Description FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures among the C (1 <= C <= 20

POJ 2112 Optimal Milking

Optimal Milking Time Limit: 2000ms Memory Limit: 30000KB This problem will be judged on PKU. Original ID: 211264-bit integer IO format: %lld      Java class name: Main FJ has moved his K (1 <= K <= 30) milking machines out into the cow pastures amon

POJ 2112 Optimal Milking 【网络流】【二分】【最短路】

题意: k c m 分别代表挤奶机数量,牛数量,和挤奶机容量. 接下来(n=k+c)n*n的矩阵A,代表挤奶机或者牛的距离,如果对角线都为0,如果非对角线没有直接路相连也为0. 1 <= K <= 30  1 <= C <= 200  1 <= M <= 15  0<=Aij<=200 求:在机器不能过载工作的前提下,最远的牛到挤奶机的距离的最小值. 思路: 1.先跑一遍FLOYD求出任何两点的最短路. 2.二分最远的距离,从源点到1到k号点的边容量为m,然