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

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

    题意:

    给定一个无向图,点i处有Ai头牛,点i处的牛棚能容纳Bi头牛,求一个最短时间T,使得在T时间内所有的牛都能进到某一牛棚里去。

    思路:

    建立一个源点和汇点,源点和牛棚的初始牛量相连,汇点和牛棚容量相连。这样跑最大流,如果最后流量等于牛的总数时,就说明是可以的。

    那么,怎么连边呢?
    二分时间,根据时间来连边,所以首先我们先跑一遍floyd计算出两点距离。然后在该时间下,如果d【i】【j】,那么就添加边(i,i',INF),表面这段路是可以走的。

    注意,这里是需要拆点的!!!

    看这个建图,这个没有拆点,那么当我们的时间T=70的时候,只有(2,3)和(3,4)是满足的,但是在图中2-4也相连了,也就是说2-4也可以走,但事实上(2,4)这条路超过了时间设定。所以,不拆点是行不通的。

    事实上,这个并不是一个二分图,任意点之间都可能有路径,所以需要拆点。

    最后,注意这道题目的数据是很大的!!!

    附上数据:http://contest.usaco.org/MAR05_4.htm

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 using namespace std;
     11 typedef long long LL;
     12 typedef pair<int,int> pll;
     13 const LL INF=1e16;
     14 const int maxn=500+5;
     15 
     16 int n,m;
     17 int full_flow;
     18 int s[maxn],t[maxn];
     19 LL g[maxn][maxn];
     20 
     21 struct Edge
     22 {
     23     int from,to,cap,flow;
     24     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
     25 };
     26 
     27 struct Dinic
     28 {
     29     int n,m,s,t;
     30     vector<Edge> edges;
     31     vector<int> G[maxn];
     32     bool vis[maxn];
     33     int cur[maxn];
     34     int d[maxn];
     35 
     36     void init(int n)
     37     {
     38         this->n=n;
     39         for(int i=0;i<n;++i) G[i].clear();
     40         edges.clear();
     41     }
     42 
     43     void AddEdge(int from,int to,int cap)
     44     {
     45         edges.push_back( Edge(from,to,cap,0) );
     46         edges.push_back( Edge(to,from,0,0) );
     47         m=edges.size();
     48         G[from].push_back(m-2);
     49         G[to].push_back(m-1);
     50     }
     51 
     52     bool BFS()
     53     {
     54         queue<int> Q;
     55         memset(vis,0,sizeof(vis));
     56         vis[s]=true;
     57         d[s]=0;
     58         Q.push(s);
     59         while(!Q.empty())
     60         {
     61             int x=Q.front(); Q.pop();
     62             for(int i=0;i<G[x].size();++i)
     63             {
     64                 Edge& e=edges[G[x][i]];
     65                 if(!vis[e.to] && e.cap>e.flow)
     66                 {
     67                     vis[e.to]=true;
     68                     d[e.to]=d[x]+1;
     69                     Q.push(e.to);
     70                 }
     71             }
     72         }
     73         return vis[t];
     74     }
     75 
     76     int DFS(int x,int a)
     77     {
     78         if(x==t || a==0) return a;
     79         int flow=0, f;
     80         for(int &i=cur[x];i<G[x].size();++i)
     81         {
     82             Edge &e=edges[G[x][i]];
     83             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
     84             {
     85                 e.flow +=f;
     86                 edges[G[x][i]^1].flow -=f;
     87                 flow +=f;
     88                 a -=f;
     89                 if(a==0) break;
     90             }
     91         }
     92         return flow;
     93     }
     94 
     95     int Maxflow(int s,int t)
     96     {
     97         this->s=s; this->t=t;
     98         int flow=0;
     99         while(BFS())
    100         {
    101             memset(cur,0,sizeof(cur));
    102             flow +=DFS(s,0x3f3f3f3f);
    103         }
    104         return flow;
    105     }
    106 }DC;
    107 
    108 void floyd()
    109 {
    110     for (int k = 1; k <= n; k++)
    111     for (int i = 1; i <= n; i++)
    112     for (int j = 1; j <= n; j++)
    113         g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
    114 }
    115 
    116 void init(LL x)
    117 {
    118     DC.init(2*n+2);
    119 
    120     for(int i=1;i<=n;i++)
    121     {
    122         DC.AddEdge(0,i,s[i]);
    123         DC.AddEdge(i+n,2*n+1,t[i]);
    124         DC.AddEdge(i,i+n,0x3f3f3f3f);
    125     }
    126 
    127     for(int i=1;i<=n;i++)
    128         for(int j=i+1;j<=n;j++)
    129         if(g[i][j]<=x)
    130     {
    131         DC.AddEdge(i,j+n,0x3f3f3f3f);
    132         DC.AddEdge(j,i+n,0x3f3f3f3f);
    133     }
    134 }
    135 
    136 int main()
    137 {
    138     //freopen("D:\input.txt","r",stdin);
    139     while(scanf("%d%d",&n,&m)!=EOF)
    140     {
    141         full_flow=0;
    142         for(int i=1;i<=n;i++)
    143         {
    144             scanf("%d%d",&s[i],&t[i]);
    145             full_flow+=s[i];
    146         }
    147 
    148         for(int i=1;i<=n;i++)
    149         {
    150             for(int j=1;j<=n;j++)
    151             g[i][j]=INF;
    152             g[i][i]=0;
    153         }
    154 
    155         for(int i=0;i<m;i++)
    156         {
    157             int u,v;
    158             LL w;
    159             scanf("%d%d%lld",&u,&v,&w);
    160             if(w<g[u][v])  g[u][v]=g[v][u]=w;
    161         }
    162 
    163         floyd();
    164 
    165         LL L=0,R=0;
    166         LL ans=-1;
    167 
    168         for(int i=1;i<=n;i++)
    169             for(int j=1;j<=n;j++)
    170             if(g[i][j]!=INF)   R=max(R,g[i][j]);
    171 
    172         while(L<=R)
    173         {
    174             LL mid=(L+R)/2;
    175             init(mid);
    176             if(DC.Maxflow(0,2*n+1)==full_flow)
    177             {
    178                 ans=mid;
    179                 R=mid-1;
    180             }
    181             else L=mid+1;
    182         }
    183         printf("%I64d
    ",ans);
    184     }
    185 
    186     return 0;
    187 }
  • 相关阅读:
    【LeetCode】17. Letter Combinations of a Phone Number
    【LeetCode】16. 3Sum Closest
    【LeetCode】15. 3Sum 三个数和为0
    【LeetCode】14. Longest Common Prefix 最长前缀子串
    【LeetCode】13. Roman to Integer 罗马数字转整数
    【LeetCode】12. Integer to Roman 整型数转罗马数
    【LeetCode】11. Container With Most Water
    【LeetCode】10. Regular Expression Matching
    Models of good programmer
    RSA Algorithm
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6918135.html
Copyright © 2011-2022 走看看