Optimal Milking(POJ2112+二分+Dinic)
题目链接:http://poj.org/problem?id=2112
题目:
题意:有k台挤奶机,c头奶牛,每台挤奶机每天最多生产m的奶,给你每个物品到其他物品的距离(除了物品到自己本省的距离为0外,两者之间没有路线直接到达也为0,此时需要将距离处理为inf),问跑最远距离的奶牛要跑多远。
思路:先用floyd将各物品间的最短距离求出来,再二分跑最远距离的奶牛走的距离x,将小于x的两者之间进行连边,流量为1,引入一个超级源点和超级汇点,我们采用方向建图的方式,让超级源点与挤奶机连边,且流量为m,奶牛与超级汇点连边,流量为1,跑一边Dinic,如果最大流为c那么ub变成mid-1,否则lb为mid+1。
代码实现如下:
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef pair<ll, ll> pll; 18 typedef pair<ll, int> pli; 19 typedef pair<int, ll> pil;; 20 typedef pair<int, int> pii; 21 typedef unsigned long long ull; 22 23 #define lson i<<1 24 #define rson i<<1|1 25 #define bug printf("*********\n"); 26 #define FIN freopen("D://code//in.txt", "r", stdin); 27 #define debug(x) cout<<"["<<x<<"]" <<endl; 28 #define IO ios::sync_with_stdio(false),cin.tie(0); 29 30 const double eps = 1e-8; 31 const int mod = 10007; 32 const int maxn = 250 + 7; 33 const double pi = acos(-1); 34 const int inf = 0x3f3f3f3f; 35 const ll INF = 0x3f3f3f3f3f3f3f; 36 37 int k, c, m, s, e, num, tot, maxflow; 38 int mp[maxn][maxn], head[maxn], d[maxn]; 39 40 queue<int> q; 41 42 struct edge { 43 int v, w, next; 44 }ed[maxn*maxn]; 45 46 void addedge(int u, int v, int w) { 47 ed[tot].v = v; 48 ed[tot].w = w; 49 ed[tot].next = head[u]; 50 head[u] = tot++; 51 ed[tot].v = u; 52 ed[tot].w = 0; 53 ed[tot].next = head[v]; 54 head[v] = tot++; 55 } 56 57 bool bfs() { 58 memset(d, 0, sizeof(d)); 59 while(!q.empty()) q.pop(); 60 q.push(s); 61 d[s] = 1; 62 while(!q.empty()) { 63 int x = q.front(); q.pop(); 64 for(int i = head[x]; ~i; i = ed[i].next) { 65 int y = ed[i].v; 66 if(ed[i].w && !d[y]) { 67 q.push(y); 68 d[y] = d[x] + 1; 69 if(y == e) return 1; 70 } 71 } 72 } 73 return 0; 74 } 75 76 int dinic(int x, int flow) { 77 if(x == e) return flow; 78 int rest = flow, k; 79 for(int i = head[x]; ~i && rest; i = ed[i].next) { 80 int y = ed[i].v; 81 if(ed[i].w && d[y] == d[x] + 1) { 82 k = dinic(y, min(rest, ed[i].w)); 83 if(!k) d[y] = 0; 84 ed[i].w -= k; 85 ed[i^1].w += k; 86 rest -= k; 87 } 88 } 89 return flow - rest; 90 } 91 92 bool check(int x) { 93 tot = 0; 94 memset(head, -1, sizeof(head)); 95 for(int i = 1; i <= k; i++) { 96 for(int j = k + 1; j <= num; j++) { 97 if(mp[i][j] <= x) { 98 addedge(i, j, 1); 99 } 100 } 101 } 102 for(int i = 1; i <= k; i++) { 103 addedge(s, i, m); 104 } 105 for(int i = k + 1; i <= num; i++) { 106 addedge(i, e, 1); 107 } 108 int flow = 0; 109 maxflow = 0; 110 while(bfs()) { 111 while((flow = dinic(s, inf))) maxflow += flow; 112 } 113 return maxflow == c; 114 } 115 116 int main() { 117 //FIN; 118 scanf("%d%d%d", &k, &c, &m); 119 num = k + c; 120 for(int i = 1; i <= num; i++) { 121 for(int j = 1; j <= num; j++) { 122 scanf("%d", &mp[i][j]); 123 if(i != j && mp[i][j] == 0) { 124 mp[i][j] = inf; 125 } 126 } 127 } 128 for(int k = 1; k <= num; k++) { 129 for(int i = 1; i <= num; i++) { 130 for(int j = 1; j <= num; j++) { 131 if(mp[i][j] > mp[i][k] + mp[k][j]) { 132 mp[i][j] = mp[i][k] + mp[k][j]; 133 } 134 } 135 } 136 } 137 s = 0, e = num + 1; 138 int ub = inf, lb = 0, mid; 139 while(ub >= lb) { 140 mid = (ub + lb) >> 1; 141 if(check(mid)) ub = mid - 1; 142 else lb = mid + 1; 143 } 144 printf("%d\n", lb); 145 return 0; 146 }
版权声明:本文允许转载,转载时请注明原博客链接,谢谢~