zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Oracle -- Create Tablespace
    EntityFramework-DBFirst-重新生成后写的验证消失(解决办法)
    UILocalNotification本地通知
    属性观察者willSet与didSet
    常用后台frame框架
    Windows常用CMD命令
    常用的格式符与转义字符
    Windows操作系统常用快捷键
    Mac操作系统常用快捷键
    srp render queue 失效
  • 原文地址:https://www.cnblogs.com/chujian123/p/3452474.html
Copyright © 2011-2022 走看看