POJ 2112 二分+最大流
题意:
有k个牛奶机跟c头牛。他们之间有路相连,农民想让每个牛能到其中一个牛奶机,又想让走路最远的牛走得最小。
题解:
求最大值最小,不出意外就是二分了
由于要限制总的路径长度,就不能对每条边限制了,于是先floyd求最短路,再二分最长路即可~
不连大于二分值的路径,连小于等于二分值的路径,做最大流就好了~
View Code
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 7 #define N 250 8 #define M 600000 9 #define INF 100000 10 11 using namespace std; 12 13 int map[N][N],m,c,k,l,r,S,T,head[N],next[M],to[M],len[M],q[M<<4],cnt,layer[N],mid,dis[N],num; 14 15 inline void add(int u,int v,int w) 16 { 17 to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; 18 to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++; 19 } 20 21 void read() 22 { 23 num=0; 24 for(int i=1;i<=k+c;i++) 25 for(int j=1;j<=k+c;j++) 26 { 27 scanf("%d",&map[i][j]); 28 if(map[i][j]==0) map[i][j]=INF; 29 } 30 for(int p=1;p<=k+c;p++)//floyd处理最短路 31 for(int i=1;i<=k+c;i++) 32 for(int j=1;j<=k+c;j++) 33 if(map[i][p]<INF&&map[p][j]<INF) 34 map[i][j]=min(map[i][p]+map[p][j],map[i][j]); 35 } 36 37 void create() 38 { 39 S=0;T=k+c+1; 40 memset(head,-1,sizeof head); 41 cnt=0; 42 for(int i=1;i<=k;i++) add(S,i,m); 43 for(int i=k+1;i<=k+c;i++) add(i,T,1); 44 for(int i=1;i<=k;i++) 45 for(int j=k+1;j<=k+c;j++) 46 if(map[i][j]<=mid) add(i,j,1); 47 } 48 49 bool bfs() 50 { 51 memset(layer,-1,sizeof layer); 52 int h=1,t=2,sta; 53 layer[S]=0; q[1]=S; 54 while(h<t) 55 { 56 sta=q[h++]; 57 for(int i=head[sta];~i;i=next[i]) 58 if(len[i]>0&&layer[to[i]]<0) 59 { 60 layer[to[i]]=layer[sta]+1; 61 q[t++]=to[i]; 62 } 63 } 64 return layer[T]!=-1; 65 } 66 67 int find(int u,int cur_flow) 68 { 69 int tmp=0,result=0; 70 if(u==T) return cur_flow; 71 for(int i=head[u];~i&&result<cur_flow;i=next[i]) 72 if(len[i]>0&&layer[to[i]]==layer[u]+1) 73 { 74 tmp=find(to[i],min(cur_flow-result,len[i])); 75 len[i]-=tmp; len[i^1]+=tmp; result+=tmp; 76 } 77 if(!result) layer[u]=-1; 78 return result; 79 } 80 81 int dinic() 82 { 83 create(); 84 int ans=0; 85 while(bfs()) ans+=find(S,INF); 86 return ans; 87 } 88 89 void go() 90 { 91 int ans; 92 l=0,r=100000; 93 while(l<=r) 94 { 95 mid=(l+r)>>1; 96 if(dinic()>=c) r=mid-1; 97 else l=mid+1; 98 } 99 printf("%d\n",l); 100 } 101 102 int main() 103 { 104 scanf("%d%d%d",&k,&c,&m); 105 read(); 106 go(); 107 return 0; 108 }
没有人能阻止我前进的步伐,除了我自己!