Ombrophobic Bovines

poj2391:http://poj.org/problem?id=2391

题意:一个人有n个农场,每个农场都一个避雨的地方,每个农场有一些牛,每个避雨的地方能容纳牛的数量是有限的。农场之间有一些道路可以连通。现在给出每个农场的牛的数量以及每个避雨点的值,问你所有的牛都找到一个避雨点的时间最短是多少。
题解:本题个人认为对于初学者来说,比较难了。看了别人的题解,本题的考察的知识点有:Floyd+二分+网络最大流,以及图论里面的拆点和建图。首先:对于所有的牛来说,如果农场是连通的,则最短的时间最坏的情况是任意两点之间距离的最大值所以要用Floyd来求n源最短路。然后最初最大的那个值。第二:建图,超级源点0,会点2*n+1,然后拆点,把那个农场拆成2*n个点,
例如:4个点的话
      1      5
      2      6
      3      7
      4      8

然后建边,以上的点,左边的点与0点建边,边权的容量为每个农改现在的牛的数量,右边的点与会点建边,边的容量为每个避雨点的容量。然后1和5之间,2和6之间建边,边权INF,然后二分答案(就是刚才的那个最大数值),对于任意的两点之间,如果两点之间的距离小于这个最大值,说明可以由i这个点牛向j移动所以i和j+n之间要建边,边权INF
每一二分答案,跑最大流,如果最大流等于牛的总数,说明这个距离满足条件,继续缩小距离再跑,知道不行就停止,则此时的距离就是最短的距离,保证所有牛都能找到避雨点的距离。
注意:本题的数据,距离会爆出int

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 using namespace std;
  7 const int INF=100000000; 
  8 const int MAXN=505;
  9 const long long INFs=100000000000000LL;
 10 int  val1[MAXN],val2[MAXN];
 11 struct Node{
 12     int f;
 13     int c;
 14 };
 15 long long dist[MAXN][MAXN];//求最短路 
 16 int pre[MAXN];//网络流的分层 
 17 Node map[MAXN][MAXN];//网络流的图 
 18 int n,m;
 19 int se,sx;//会点和源点 
 20 bool BFS(){//层次网络 
 21     memset(pre,0,sizeof(pre));
 22     queue<int>Q;
 23     Q.push(0);
 24     pre[0]=1;
 25     while(!Q.empty()){
 26         int v=Q.front();
 27         Q.pop();
 28     for(int i=0;i<=2*n+1;i++)
 29        if(!pre[i]&&map[v][i].c-map[v][i].f){
 30          pre[i]=pre[v]+1;
 31           Q.push(i);    
 32         }
 33      }
 34    return pre[se]!=0;        
 35 }
 36 int dinic(int pos,int flow){//网路流 
 37       int f=flow;
 38       if(pos==se)
 39       return flow;
 40      for(int i=0;i<=2*n+1;i++){
 41          if(map[pos][i].c-map[pos][i].f&&pre[i]==pre[pos]+1){
 42              int a=map[pos][i].c-map[pos][i].f;
 43              int temp=dinic(i,min(a,flow));
 44              map[pos][i].f+=temp;
 45              map[i][pos].f-=temp;
 46              flow-=temp;
 47          }
 48      }
 49     return f-flow;
 50 }
 51 int slove(){//总流 
 52     int sum=0;
 53     while(BFS()) 
 54       sum+=dinic(sx,INF);
 55     return sum;
 56 }
 57 void build(long long limit){//建图 
 58     memset(map,0,sizeof(map));
 59     for(int i=1;i<=n;i++)
 60         if(val1[i]){
 61             map[0][i].c=val1[i];
 62             map[0][i].f=0;
 63             map[i][i+n].c=INF;
 64             map[i][i+n].f=0;
 65         }
 66     for(int i=1;i<=n;i++){
 67         if(val2[i]){
 68             map[i+n][2*n+1].c=val2[i];
 69             map[i+n][2*n+1].f=0;
 70         }
 71     } 
 72     for(int i=1;i<=n;i++)
 73       for(int j=1;j<=n;j++){
 74             if(dist[i][j]<=limit&&i!=j){
 75                 map[i][j+n].c=INF;
 76                 map[i][j+n].f=0;
 77             }
 78       }     
 79 }
 80 long long Floyd(){//求n源最短路 
 81     for(int k=1;k<=n;k++)
 82        for(int i=1;i<=n;i++)
 83          for(int j=1;j<=n;j++){
 84              if(i!=k&&i!=j&&k!=j&&dist[i][k]+dist[k][j]<dist[i][j])
 85                 dist[i][j]=dist[i][k]+dist[k][j];
 86          }
 87         long long ans=0;//注意这里初始化,因为一下的可能不会执行,可能没有满足条件ans 
 88        for(int i=1;i<=n;i++)
 89          for(int j=1;j<=n;j++)
 90            if(dist[i][j]<INFs&&dist[i][j]>ans)
 91               ans=dist[i][j];
 92        return ans;
 93 }
 94 void init(){//初始化 
 95     memset(val1,0,sizeof(val1));
 96     memset(val2,0,sizeof(val2));
 97     for(int i=1;i<=n;i++)
 98       for(int j=1;j<=n;j++)
 99          dist[i][j]=INFs;
100 }
101 int main(){
102     int c,f,u,v,sum;long long w;
103     while(~scanf("%d%d",&n,&m)){
104         init();sum=0;sx=0;se=2*n+1;
105         for(int i=1;i<=n;i++){
106             scanf("%d%d",&f,&c);
107              val1[i]=f;val2[i]=c;
108              sum+=f;
109         }
110       for(int i=1;i<=m;i++){
111           scanf("%d %d %I64d",&u,&v,&w);
112           if(w<dist[u][v])
113           dist[u][v]=dist[v][u]=w;
114      }
115         long long r=Floyd(),ans=-1,l=0;
116          while(l<=r){//二分答案,不断缩小答案 
117              long long mid=(l+r)/2;
118              build(mid);
119             if(slove()>=sum){
120                   r=mid-1;ans=mid;
121              }
122             else
123                  l=mid+1;
124         }
125        printf("%I64d
",ans);
126     }
127 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3452474.html