POJ 2391 Ombrophobic Bovines(二分+拆点+最大流)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\\n",ans);
184     }
185 
186     return 0;
187 }

 

以上是关于POJ 2391 Ombrophobic Bovines(二分+拆点+最大流)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2391 Ombrophobic Bovines

POJ 2391 Ombrophobic Bovines

poj2391 Ombrophobic Bovines

POJ2391 Ombrophobic Bovines(网络流)(拆点)

POJ2391 Ombrophobic Bovines 网络流拆点+二分+floyed

POJ 2391 Ombrophobic Bovines(二分+拆点+最大流)