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 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2848500.html