poj 2112 Optimal Milking 最大流
http://poj.org/problem?id=2112
【题意】 k个机器,每个机器最多服务m头牛。c头牛,每个牛需要1台机器来服务。给出一个矩阵表示每两个实体之间的直接距离。(注意两个实体没有直接
距离的时候用0表示) 问:让所有的牛都被服务的情况下,使走的最远的牛的距离最短,求这个距离。
【思路】 先用floyd求出每两个实体间的最短距离,再二分所求的距离len。
【建图】 源点向每个机器连边,容量为m。每个机器向距离小于len的牛连边,容量为1。每头牛向汇点连边,容量为1。若最大流为牛的数量,说明每头牛都
服务到了,这个len可行。
1 #include<iostream> 2 #include<vector> 3 #include<cstring> 4 #include<queue> 5 #include<cstdio> 6 using namespace std; 7 #define maxx 250 8 #define INF 9999999 9 10 int c[maxx][maxx],f[maxx][maxx],p[maxx], a[maxx]; 11 int d[maxx][maxx]; 12 int machine,cow,maxc; 13 14 void add(int u,int v,int w) 15 { 16 c[u][v]=w; 17 } 18 19 int maxflow(int s,int t,int n) 20 { 21 queue<int> q; 22 memset(f,0,sizeof(f)); 23 int flow=0; 24 while(1) 25 { 26 memset(a,0,sizeof(a)); 27 a[s] = INF; 28 q.push(s); 29 30 while(!q.empty()) 31 { 32 int u = q.front(); 33 q.pop(); 34 for(int v = 1; v <= n; v++) if(!a[v] && c[u][v] > f[u][v]) 35 { 36 p[v] = u; 37 q.push(v); 38 a[v] = min(a[u], c[u][v]-f[u][v]); 39 } 40 } 41 42 if(a[t] == 0) 43 break; 44 for(int u = t; u != s; u = p[u]) 45 { 46 f[p[u]][u] += a[t]; 47 f[u][p[u]] -= a[t]; 48 } 49 flow += a[t]; 50 } 51 return flow; 52 } 53 54 bool ok(int x) 55 { 56 memset(c,0,sizeof(c)); 57 memset(f,0,sizeof(f)); //!! 注意要清零啊!!泪奔~ 58 int n=machine+cow; 59 for(int i=1; i<=machine; i++) 60 { 61 add(0,i,maxc); 62 for(int j=machine+1; j<=machine+cow; j++) 63 if(d[i][j]<=x) 64 add(i,j,1); 65 } 66 for(int i=machine+1; i<=n; i++) 67 add(i,n+1,1); 68 int flow; 69 flow=maxflow(0,n+1,n+1); 70 // printf("flow %d x %d\n",flow,x); 71 if(flow==cow) 72 return true; 73 return false; 74 } 75 76 int solve(int max1) 77 { 78 int left=0,right=max1,minn=right; 79 while(left<=right) //之前习惯性写成了 left<right了。。 80 { 81 int mid; 82 mid=(left+right)/2; 83 if(ok(mid)) 84 { 85 minn=min(minn,mid); 86 right=mid-1; 87 } 88 else left=mid+1; 89 } 90 return minn; 91 } 92 93 int main() 94 { 95 int k,c,m; 96 while(~scanf("%d%d%d",&machine,&cow,&maxc)) 97 { 98 int n=machine+cow; 99 for(int i=1; i<=n; i++) 100 for(int j=1; j<=n; j++) 101 { 102 scanf("%d",&d[i][j]); 103 if(d[i][j]==0&&i!=j) 104 d[i][j]=INF; 105 } 106 107 for(int m=1; m<=n; m++) 108 for(int i=1; i<=n; i++) 109 for(int j=1; j<=n; j++) 110 d[i][j]=min(d[i][j],d[i][m]+d[m][j]); 111 112 int max1=0; 113 for(int i=1; i<=n; i++) 114 for(int j=1; j<=n; j++) 115 max1=max(max1,d[i][j]); 116 117 printf("%d\n",solve(max1)); 118 } 119 return 0; 120 }