zoukankan      html  css  js  c++  java
  • POJ 2391--Ombrophobic Bovines(最大流(拆点)+二分+最短路)

    Ombrophobic Bovines

    Description

    FJ's cows really hate getting wet so much that the mere thought of getting caught in the rain makes them shake in their hooves. They have decided to put a rain siren on the farm to let them know when rain is approaching. They intend to create a rain evacuation plan so that all the cows can get to shelter before the rain begins. Weather forecasting is not always correct, though. In order to minimize false alarms, they want to sound the siren as late as possible while still giving enough time for all the cows to get to some shelter. 

    The farm has F (1 <= F <= 200) fields on which the cows graze. A set of P (1 <= P <= 1500) paths connects them. The paths are wide, so that any number of cows can traverse a path in either direction. 

    Some of the farm's fields have rain shelters under which the cows can shield themselves. These shelters are of limited size, so a single shelter might not be able to hold all the cows. Fields are small compared to the paths and require no time for cows to traverse. 

    Compute the minimum amount of time before rain starts that the siren must be sounded so that every cow can get to some shelter.

    Input

    * Line 1: Two space-separated integers: F and P 

    * Lines 2..F+1: Two space-separated integers that describe a field. The first integer (range: 0..1000) is the number of cows in that field. The second integer (range: 0..1000) is the number of cows the shelter in that field can hold. Line i+1 describes field i. 

    * Lines F+2..F+P+1: Three space-separated integers that describe a path. The first and second integers (both range 1..F) tell the fields connected by the path. The third integer (range: 1..1,000,000,000) is how long any cow takes to traverse it.

    Output

    * Line 1: The minimum amount of time required for all cows to get under a shelter, presuming they plan their routes optimally. If it not possible for the all the cows to get under a shelter, output "-1".

    Sample Input

    3 4
    7 2
    0 4
    2 6
    1 2 40
    3 2 70
    2 3 90
    1 3 120

    Sample Output

    110

     

    题意:牛牛一开始分散在各个草场,每个草场存在一个有容纳上限的避难所,草场之间有道路连接(双向),并且路程耗时和道路长度成正比。问当下雨时,所有牛转移至避难所的最短时间。

     

    思路:二分求答案T。先跑一遍floyd求最短路。

    构图方面,将每个点拆分成两个点i, i+n,设置源点s和汇点t, 按照 s-->i, i+n-->t,i<-->j 建立网络,容量分别为一开始牛的只数,避难所上限,INF。

    对于每一个T,重新构图, 如果对于点i, j, 最短路dis[i][j]<=T,那么i-->j+n 连一条容量为INF的边,表示这两个点的牛能在T时间内转移。

    然后求最大流,如果最大流大于等于牛的总只数,那么这个T是满足条件的,继续二分下去。

    。。。这道题改了很长时间,最后发现是函数返回long long 和 int 搞乱了。

     

    AC代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 #include<queue>
      6 using namespace std;
      7 typedef long long LL;
      8 const int MAXN=2e3+10;
      9 const int INF=1e9+10;
     10 const LL INFLL=1e16+5;
     11 struct Edge{
     12     int to;
     13     int c;
     14     int rev;
     15 };
     16 LL dis[MAXN][MAXN];
     17 int sum=0,s,t,n,m;
     18 vector<Edge> vec[MAXN];
     19 int in[MAXN],out[MAXN];
     20 int level[MAXN],iter[MAXN];
     21 void floyd(){
     22     for(int k=1;k<=n;k++){
     23         for(int i=1;i<=n;i++){
     24             for(int j=1;j<=n;j++){
     25                 dis[i][j]=min(dis[i][j], dis[i][k]+dis[k][j]);
     26             }
     27         }
     28     }
     29     return;
     30 }
     31 void add_edge(int a, int b, int cap){
     32     vec[a].push_back((Edge){b, cap, vec[b].size()});
     33     vec[b].push_back((Edge){a, 0, vec[a].size()-1});
     34     return;
     35 }
     36 
     37 int dfs(int S, int T, int flow){
     38     if(S==T) return flow;
     39     
     40     for(int &i=iter[S];i<vec[S].size();i++){
     41         Edge &e=vec[S][i];
     42         if(level[S]<level[e.to]&&e.c>0){
     43             int d=dfs(e.to, T, min(e.c, flow));
     44             if(d>0){
     45                 e.c-=d;
     46                 vec[e.to][e.rev].c+=d;
     47                 return d;
     48             }
     49         }
     50     }
     51     return 0;
     52 }
     53 void rebuild(LL T)
     54 {
     55     for(int i=0;i<MAXN;i++)
     56         vec[i].clear();
     57     for(int i=1;i<=n;i++){
     58         add_edge(s, i, in[i]);
     59         add_edge(i+n, t, out[i]);
     60         add_edge(i, i+n, INF);
     61     }
     62     for(int i=1;i<=n;i++){
     63         for(int j=i+1;j<=n;j++){
     64             if(dis[i][j]<=T){
     65                 add_edge(i, j+n, INF);
     66                 add_edge(j, i+n, INF);
     67             }     
     68         }
     69     }
     70 }
     71 void bfs(){
     72     memset(level, -1, sizeof(level));
     73     queue<int> q;
     74     level[s]=0;
     75     q.push(s);
     76     while(!q.empty()){
     77         int v=q.front();q.pop();
     78         for(int i=0;i<vec[v].size();i++){
     79             Edge &e=vec[v][i];
     80             if(e.c>0&&level[e.to]<0){
     81                 level[e.to]=level[v]+1;
     82                 q.push(e.to);
     83             }
     84         }
     85     }
     86     return;
     87 }
     88 int max_flow(LL T){
     89     rebuild(T);
     90     int res=0,flow;
     91     while(1){
     92         bfs();
     93         if(level[t]<0) return res;
     94         memset(iter, 0, sizeof(iter));
     95         while((flow=dfs(s, t, INF)) > 0){
     96             res+=flow;
     97         }
     98     }
     99     //cout<<res<<endl;
    100     return res;
    101 }
    102 LL solve(LL l, LL r){
    103     LL mid,ans=-1;
    104     while(l<=r){
    105         mid=(l+r)/2;
    106         if(max_flow(mid)>=sum){//dinic算法
    107             ans=mid;
    108             r=mid-1;
    109         } 
    110         else l=mid+1;
    111         //cout<<ans<<endl;
    112     }
    113     return ans;
    114 }
    115 int main()
    116 {
    117     int a,b,w;
    118     scanf("%d %d", &n, &m);
    119     s=0,t=2*n+1;
    120     for(int i=1;i<=n;i++){
    121         scanf("%d %d",&in[i], &out[i]);
    122         sum+=in[i];
    123     }
    124     for(int i=1;i<=n;i++)
    125         for(int j=1;j<=n;j++)
    126             dis[i][j]=(i==j)?0:INFLL;
    127     for(int i=0;i<m;i++){
    128         scanf("%d %d %d", &a, &b, &w);
    129         if(dis[a][b]>w)
    130             dis[a][b]=dis[b][a]=w;
    131     }
    132     floyd();
    133     LL T=solve(0, INFLL-1);
    134     printf("%lld
    ", T);
    135     return 0;
    136 }
  • 相关阅读:
    解决运行docker命令要用sudo的问题
    python3 http.server 本地服务支持跨域
    Linux 命令速记本
    截取某段时间内的日志
    centos7 安装postgresql10
    centos 7 安装 mail
    centos7 mail
    centos7 mysql 5.7 官网下载tar安装
    修改storm ui 默认端口
    redis-trib构建集群
  • 原文地址:https://www.cnblogs.com/MasterSpark/p/7572251.html
Copyright © 2011-2022 走看看