zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    HDU5418.Victor and World(状压DP)
    POJ2686 Traveling by Stagecoach(状压DP)
    POJ3254Corn Fields(状压DP)
    HDU5407.CRB and Candies(数论)
    CodeForces 352D. Jeff and Furik
    CodeForces 352C. Jeff and Rounding(贪心)
    LightOj 1282 Leading and Trailing
    Ural 1057. Amount of Degrees(数位DP)
    HDU 2089 不要62 (数位DP)
    HDU5366 The mook jong (DP)
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9503516.html
Copyright © 2011-2022 走看看