题目链接:http://poj.org/problem?id=2112
和POJ2455很像,也是求最大值最小,当时就想到了二分。具体做法就是:先求出每头牛到到牛奶机器的最短路,用spfa或dijkstra(也可以用floyd直接搞)从每个牛奶机器求一次最短路即可,那么这里就可以很容易的看出来可以直接用二分图最大匹配来依次二分求解最佳值,当然也可以用网络流来求最大流,加一个超级源点和超级汇点,源点到每头牛的容量为1,每头牛到每个牛奶机器的容量为1,每个牛奶机器到汇点的容量为m,那么就可以二分来做了。这个题目用二分图做法显然更简单,更方便,但我还是用网络流模型来做了,详细见代码。
1 //STATUS:G++_AC_125MS_1368KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 #include<map> 13 using namespace std; 14 #define LL long long 15 #define Max(a,b) ((a)>(b)?(a):(b)) 16 #define Min(a,b) ((a)<(b)?(a):(b)) 17 #define mem(a,b) memset(a,b,sizeof(a)) 18 #define lson l,mid,rt<<1 19 #define rson mid+1,r,rt<<1|1 20 const int MAX=240,INF=0x3f3f3f3f; 21 22 int inq[MAX],w1[MAX][MAX],w2[MAX][MAX],cap[MAX][MAX],d[MAX],cur[MAX]; 23 int n,m,k,nm,limit,maxlen,s,t; 24 25 void spfa(int s) 26 { 27 int i,x; 28 mem(d,0x3f);mem(inq,0); 29 queue<int> q; 30 q.push(s); 31 d[s]=0; 32 while(!q.empty()){ 33 x=q.front();q.pop(); 34 inq[x]=0; 35 for(i=1;i<=nm;i++){ 36 if(w1[x][i] && d[x]+w1[x][i]<=d[i]){ 37 d[i]=d[x]+w1[x][i]; 38 if(!inq[i]){ 39 inq[i]=1; 40 q.push(i); 41 } 42 } 43 } 44 } 45 } 46 47 int bfs() 48 { 49 int x,i; 50 queue<int> q; 51 q.push(s); 52 mem(d,0); 53 d[s]=1; 54 while(!q.empty()){ 55 x=q.front();q.pop(); 56 for(i=1;i<=nm;i++){ 57 if(w2[x][i] && w2[x][i]<=limit && cap[x][i] && !d[i]){ 58 d[i]=d[x]+1; 59 q.push(i); 60 } 61 } 62 } 63 return d[t]; 64 } 65 66 int dfs(int x,int a) 67 { 68 if(x==t || a==0)return a; 69 int f,flow=0; 70 for(int& i=cur[x];i<=nm;i++){ 71 if(w2[x][i] && w2[x][i]<=limit && d[x]+1==d[i] && (f=dfs(i,Min(a,cap[x][i])))>0){ 72 cap[x][i]-=f; 73 cap[i][x]+=f; 74 flow+=f; 75 a-=f; 76 if(!a)break; 77 } 78 } 79 return flow; 80 } 81 82 int dinic() 83 { 84 int flow=0; 85 while(bfs()){ 86 mem(cur,0); 87 flow+=dfs(s,2*INF); 88 } 89 return flow; 90 } 91 92 int binary() 93 { 94 int i,j,low=1,high=maxlen,mid,t; 95 while(low<high){ 96 mid=(low+high)>>1; 97 mem(cap,0); 98 for(i=n+1;i<=nm-2;i++) 99 for(j=1;j<=n;j++)cap[i][j]=1; 100 for(i=nm-1,j=1;j<=n;j++)cap[j][i]=k; 101 for(i=nm,j=n+1;j<=nm-2;j++)cap[i][j]=1; 102 limit=mid; 103 t=dinic(); 104 if(t<m)low=mid+1; 105 else high=mid; 106 } 107 return low; 108 } 109 110 int main() 111 { 112 // freopen("in.txt","r",stdin); 113 int i,j; 114 while(~scanf("%d%d%d",&n,&m,&k)) 115 { 116 nm=n+m; 117 s=nm+2,t=nm+1; 118 mem(w2,0); 119 maxlen=-INF; 120 for(i=1;i<=nm;i++) 121 for(j=1;j<=nm;j++) 122 scanf("%d",&w1[i][j]); 123 124 for(i=1;i<=n;i++){ 125 spfa(i); 126 for(j=1;j<=nm;j++){ 127 w2[i][j]=w2[j][i]=d[j]; 128 if(d[j]>maxlen)maxlen=d[j]; 129 } 130 } 131 132 nm+=2; 133 for(i=nm-1,j=1;j<=n;j++) 134 w2[i][j]=w2[j][i]=1; 135 for(i=nm,j=n+1;j<=nm-2;j++) 136 w2[i][j]=w2[j][i]=1; 137 138 printf("%d\n",binary()); 139 } 140 return 0; 141 }