POJ 2112 Optimal Milking 【网络流】【flyod】【二分】

居然手写dinic一次过了,激动。。

 这题构建网络流模型的思路还是蛮巧妙的,想要解题要想到两个题目里面给的暗示。

1.each milking machine process at most M cows each day,这是赤裸裸的网络流啊!由此联想到每个milk machine到汇点的capacity是M,那起点到每个cow的capacity都是1,管道里流的奶牛。那么问题变成了剩下的网络怎么建?牛与牛,机器与机器,牛与机器之间有没有管道。

2.这要想到第二点每个奶牛可以走很多次路最终到达milking machine,也就是说中间经过了哪些奶牛和机器是无关的,只有最后奶牛停在了哪个机器上是有关的。所以想到flyod一遍,求出奶牛到所有machine的最近距离;然后由于求的是最近最远距离,所以我们二分枚举。如果奶牛A到机器B的最近距离大于当前枚举的最远距离,那就走不了,capacity为0;反之capacity为1。

话说这还是我第一次写flyod。。把动态规划用在图论里解决最短路问题,真妙啊。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<deque>
  4 #define INF 1000000000
  5 using namespace std;
  6 
  7 int dist[250][250],ans,K,C,M;
  8 int G[250][250];
  9 
 10 int layer[250],vis[250];
 11 bool countlayer(){//还有没有增广路 
 12     memset(layer,0,sizeof(layer));
 13     deque<int> q;
 14     q.push_back(0); layer[0]=1;
 15     while(!q.empty()){
 16         int nd = q.front(); q.pop_front();
 17         if(nd==K+C+1) return true;
 18         for(int i=1;i<=K+C+1;i++){
 19             if(G[nd][i] && layer[i]==0){
 20                 layer[i]=layer[nd]+1;
 21                 q.push_back(i);
 22             }
 23         }
 24     }
 25     return false;
 26 }
 27 
 28 int dinic(){
 29     int max_flow=0;
 30     while( countlayer() ){
 31         memset(vis,0,sizeof(vis));
 32         deque<int> q;
 33         q.push_back(0); vis[0]=1;
 34         while(!q.empty()){
 35             int nd=q.back();
 36             if(nd==K+C+1){//找到一条增广路 
 37                 int minflow=INF,u;
 38                 for(int i=0;i<q.size()-1;i++){//从上到下的最小管道 
 39                     int from=q[i],to=q[i+1];
 40                     if(G[from][to]<minflow){
 41                         minflow=G[from][to];
 42                         u=from;
 43                     }
 44                 }
 45                 //做增广 
 46                 for(int i=0;i<q.size()-1;i++){
 47                     int from=q[i],to=q[i+1];
 48                     G[from][to]-=minflow;
 49                     G[to][from]+=minflow;
 50                 }
 51                 max_flow+=minflow;
 52                 //回溯
 53                 while(!q.empty() && q.back()!=u ){
 54                     vis[q.back()]=0;
 55                     q.pop_back();
 56                 }    
 57             }
 58             else{//继续往下搜
 59                 int i;
 60                 for(i=1;i<=K+C+1;i++){
 61                     if( layer[nd]+1==layer[i] && vis[i]==0 && G[nd][i] ){
 62                         vis[i]=1;
 63                         q.push_back(i);
 64                         break;
 65                     }
 66                 }
 67                 if(i==K+C+2) q.pop_back();
 68             }
 69         }
 70     }
 71     return max_flow;
 72 }
 73 
 74 bool check(int dis){
 75 
 76     memset(G,0,sizeof(G));
 77     for(int i=K+1;i<=K+C;i++) G[0][i]=1;
 78     for(int i=1;i<=K;i++) G[i][K+C+1]=M;
 79     
 80     for(int i=K+1;i<=K+C;i++){
 81         for(int j=1;j<=K;j++){
 82             if(dist[i][j]<=dis) G[i][j]=1;
 83         }
 84     }
 85 
 86     if( dinic()==C ) return true;
 87     return false;
 88 } 
 89 
 90 
 91 int main(){
 92     
 93     cin>>K>>C>>M;    
 94     for(int i=1;i<=K+C;i++){
 95         for(int j=1;j<=K+C;j++){
 96             cin>>dist[i][j];//k=0
 97             if(dist[i][j]==0) dist[i][j]=INF;
 98         }
 99     }
100     //1...k   milking machine
101     //k+1 k+c  cows
102         
103     for(int k=1;k<=K+C;k++)
104      for(int i=1;i<=K+C;i++)
105       for(int j=1;j<=K+C;j++){
106           //i->j  中间节点小于等于k 
107         dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]);      
108     }
109         
110     int start=INF,end=-1;
111     for(int i=K+1;i<=K+C;i++){
112         for(int j=1;j<=K;j++){
113             start=min(start,dist[i][j]);
114             end=max(end,dist[i][j]);
115         }
116     }
117     int mid;
118     while(end>=start){    
119         mid = (end+start)/2;
120         if( check(mid) ){
121             ans=mid;
122             end=mid-1;
123         }
124         else start=mid+1;
125     }
126     
127     cout<<ans;
128     return 0;    
129 }

猜你喜欢

转载自www.cnblogs.com/ZhenghangHu/p/9503516.html
今日推荐