POJ-2112 Optimal Milking 二分+最大流或二分图匹配

  题目链接: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 }

你可能感兴趣的:(poj)