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 }
  • 相关阅读:
    第一份随笔
    慢哈希算法
    彩虹表
    基于Wireshark验证网站口令认证传输方案
    electron学习笔记2
    基于原型的软件需求获取
    《小学四则运算练习软件》结对项目报告
    201571030109 小学四则运算练习软件项目报告
    201571030109 《构建之法》速读
    个人学期总结
  • 原文地址:https://www.cnblogs.com/ZhenghangHu/p/9503516.html
Copyright © 2011-2022 走看看