POJ2391 Ombrophobic Bovines(二分+拆点+最大流)
来源:互联网 发布:php数据类型的意思 编辑:程序博客网 时间:2024/06/03 15:08
链接:http://poj.org/problem?id=2391
题意:
有n个点,m条边(无向边),先输入n个点的信息,前面那个是这个点内已经有的牛,后面的是这个点最多可以容纳几头牛。m条边就是起点,终点,所需时间。问:所有奶牛都在点内安排好,所需的最少时间。如果无解输出-1。
根据题意,我们会想到一个思路,就是二分最大距离,然后跑最大流,这是一个初级思路,我写了这个之后发现是错的,仔细思考以后发现这样一种情况。不同的点间接连接着,我们二分的最大距离是x的话,这些点的距离最大确实都不超过x,但是加起来却超过了x,这样不符合我们的要求。我看了别人的博客,学习到一个思路就是拆点。
把每个点拆成入点和出点两种。那么我们在建图的时候,可以这样建图。
源点->每个点的入点 权值为这个点已存在的牛。
每个点的出点->汇点 权值为这个点可以容纳的牛。
每个点的入点->自己的出点 权值为所有牛的总数,因为每条路可以容纳无数牛。
最关键的是点与点之间的路径怎么建立。我们的目的是为了避免间接相连,也就是说,每条路径存的都要是直达。从前面的边可以看出,从每个点的出点出去之后都是汇点,而且,每个点的入点都是从源点得到的。所以要直达的话,点之间的路径就是符合条件的边(u,v)的(u)入点->(v)出点。
知道这些条件以后,就是二分距离,然后最大流了。
这题还有一个地方需要注意,就是一开始在图中设置的距离的最大值的问题,我们考虑有200个点,每个点 i 只和i + 1相连,而且距离是最大值1e9,那么点 1 和点200的距离就是199*1e9,差不多200*1e9就是2e11。因为一开始最大值设置的不对,一直错没有发现原因。
Accepted 1708K 282MS G++ 2850B
#include<cstdio>#include<cstring>#include<string>#include<queue>#include<map>#include<iostream>#include<vector>#include<cstdlib>#include<cmath>#include<stack>#include<cctype>#include<set>#include<cassert>#include<algorithm>using namespace std;typedef long long ll;const int INF=1e9+7;typedef pair<int,int> pii;#define in(x) (x)#define out(x) (x+n)struct node{ int cow,last;}val[210];int n,m,Cow,st,ed;ll pic[210][210];void floyd(){ for(int k=1;k<=n;k++){ for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(pic[i][j]>pic[i][k]+pic[k][j]){ pic[i][j]=pic[i][k]+pic[k][j]; } } } }}int F[410][410];int d[410];void build(ll v){ st=0;ed=n+n+1; memset(F,0,sizeof F); for(int i=1;i<=n;i++){ F[st][in(i)]=val[i].cow; F[out(i)][ed]=val[i].last; F[in(i)][out(i)]=Cow; } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(pic[i][j]<=v){ F[in(i)][out(j)]=Cow; } } }}bool BFS(){ queue<int> Q; memset(d,-1,sizeof d); d[st]=0;Q.push(st); while(!Q.empty()){ int s=Q.front();Q.pop(); for(int i=1;i<=ed;i++){ if(F[s][i]>0&&d[i]<0){ d[i]=d[s]+1;Q.push(i); } } } return d[ed]>0;}int DFS(int s,int t,int flow){ if(s==t||flow==0)return flow; int ans=0; for(int i=1;i<=ed;i++){ if(F[s][i]>0&&d[i]==d[s]+1){ int ff=DFS(i,t,min(flow,F[s][i])); if(ff>0){ F[s][i]-=ff; F[i][s]+=ff; ans+=ff; flow-=ff; if(!flow)break; } } } if(!ans)d[s]=-1; return ans;}int dinic(ll v){ build(v); int ans=0; while(BFS()){ ans+=DFS(st,ed,INF); } return ans;}int main(){// freopen("D://input.txt","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d%d",&val[i].cow,&val[i].last); Cow+=val[i].cow; } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i!=j)pic[i][j]=2e11; else pic[i][j]=0; } } for(int i=1;i<=m;i++){ int a,b,c;scanf("%d%d%d",&a,&b,&c); if(pic[a][b]>c)pic[a][b]=pic[b][a]=c; } floyd(); ll l=0,r=0,ans=-1; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(pic[i][j]!=2e11) r=max(r,pic[i][j]); } } while(l<=r){ ll m=(l+r)>>1; if(dinic(m)==Cow){ ans=m;r=m-1; } else l=m+1; } printf("%I64d\n",ans); return 0;}
- POJ2391 Ombrophobic Bovines(二分+拆点+最大流)
- POJ2391 Ombrophobic Bovines 二分+最大流dinic
- poj2391 Ombrophobic Bovines(二分+floyd+最大流)
- 【poj2391】Ombrophobic Bovines 二分+最大流+floyd
- 【POJ2391】Ombrophobic Bovines【二分】【Floyd】【最大流】
- POJ2391.Ombrophobic Bovines(不喜欢雨的奶牛)——floyd+二分+拆点+最大流
- poj2391 Ombrophobic Bovines 拆点+网络流
- 【poj2391】【最大流】Ombrophobic Bovines
- POJ2391:Ombrophobic Bovines floyd+二分答案+最大流
- POJ 2391 Ombrophobic Bovines 二分最大流+拆点
- [网络流]poj2391 Ombrophobic Bovines
- POJ2391 Ombrophobic Bovines 网络流拆点+二分+floyed
- POJ--2391[Ombrophobic Bovines] Floyd+最大流判定(拆点)+二分答案
- poj 2391 Ombrophobic Bovines(二分枚举+floyd+最大流+拆点)
- POJ 2391 Ombrophobic Bovines 二分拆点最大流+floyd(高精度)
- Ombrophobic Bovines poj 2391 二分+拆点+最大流sap模板
- POJ--2391--Ombrophobic Bovines【拆点+Floyd+Dinic优化+二分答案】网络最大流
- poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap
- JVM 栈 堆 内存泄露 调优
- 1033. To Fill or Not to Fill (25)
- poj 2594 (机器人覆盖所有顶点)
- C++ Primer Plus Chapter3
- 关于android系统对AndroidManifest文件的解析机制
- POJ2391 Ombrophobic Bovines(二分+拆点+最大流)
- URAL 1091 Tmutarakan Exams
- 利用KVO监听属性值的变化
- 匿名内部类精讲
- 面试笔试杂项积累-leetcode 291-300
- 隐藏iOS状态栏(iOS 9)
- USACO 1.5 pprime
- CentOS、Ubuntu、Debian三个linux比较异同
- 高速下载苹果官方文档(百度云盘)