POJ 2391 多源多汇拆点最大流 +flody+二分答案
题意:在一图中,每个点有俩个属性:现在牛的数量和雨棚大小(下雨时能容纳牛的数量),每个点之间有距离,
给出牛(速度一样)在顶点之间移动所需时间,问最少时间内所有牛都能避雨。
模型分析:多源点去多汇点(此题源点也可能是汇点(源汇同点)),所以我的方法是:建立超级源点和超级
汇点,超级源点连想所有点,容量为该店本来的牛数量,在把各点拆成如图(略丑),到汇点的容量分别为
避雨容纳量,点点之间容量可以无限大。folyd求任意两点的最短路后,二分最大时间建图,枚举求最大之最小即可。
未1A原因:
1:开始时为了偷取一点时间复杂度,源点和汇点的部分图按全局先建立了,导致链式前向星操作失控,
也因为这样更好的理解了head[i]的作用;
2:开始没有拆点,这题明显和POJ2112不同,因为目标点(多个)和出发点(多个)可能在同一个点,
必需拆点i --》i+n+1(n+1是超级汇点)。
3.注意此题数据范围,一条边可能到10^10,多边时必然爆INT,用longlong,在函数传参的时候也别忘记!
还有就是几条边,200*200*2+200*2*2(200个点拆后俩俩有双向边+超级源点和汇点)。
PS:为什么我的dinic时间要700MS+。。。。
#include<iostream>//750MS
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
int n,m;const int inf =0x3f3f3f3f;
long long a[210][210]; long long minmax=0;int num=0;
int sh=0; int numcow=0;
int e[81001][3];int head[410]; int cow[210];int shelt[210]; //链式前向星二维数组表示法,0:to,1:pre,2:wight;
void folyd() //最短路不用说
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int ii=1;ii<=n;ii++)
if(a[j][ii]>a[j][i]+a[i][ii])
{
a[j][ii]=a[j][i]+a[i][ii];
if(a[j][ii]>minmax)minmax=a[j][ii]; //枚举上界
}
}
void build(long long limit) //建图
{
num=0;
for(int i=0;i<=2*n+2;i++)
head[i]=-1;
for(int i=1;i<=n;i++) //超级源点和汇点
{
e[num][0]=i;e[num][1]=head[0];head[0]=num;
e[num++][2]=cow[i];
e[num][0]=0;e[num][1]=head[i];head[i]=num;
e[num++][2]=0;
e[num][0]=n+1;e[num][1]=head[i+n+1];head[i+n+1]=num;
e[num++][2]=shelt[i];
e[num][0]=i+n+1;e[num][1]=head[n+1];head[n+1]=num;
e[num++][2]=0;
}
for(int i=1;i<=n;i++) //限制下可以添加的边
for(int j=1;j<=n;j++)
if(a[i][j]<=limit)
{
e[num][0]=j+n+1;e[num][1]=head[i];head[i]=num;
e[num++][2]=numcow;
e[num][0]=i;e[num][1]=head[j+n+1];head[j+n+1]=num;
e[num++][2]=0;
}
}
int level[410];int vis[410];
bool bfs() //bfs+dfs,dinic算法
{
for(int i=0;i<=2*n+2;i++)
vis[i]=level[i]=0;
queue<int>q;
q.push(0);vis[0]=1;
while(!q.empty())
{
int cur=q.front();q.pop();
for(int i=head[cur];i!=-1;i=e[i][1])
{ int to=e[i][0];
if(!vis[to]&&e[i][2]>0)
{
vis[to]=1;
level[to]=level[cur]+1;
if(to==n+1)return 1;
q.push(to);
}
}
}
return vis[n+1];
}
int dfs(int uu,int minf)
{
if(uu==n+1||minf==0)return minf;
int sum=0,f;
for(int i=head[uu];i!=-1&&minf;i=e[i][1])
{ int to=e[i][0];
if(level[to]==level[uu]+1&&e[i][2]>0)
{
f=dfs(to,minf<e[i][2]?minf:e[i][2]);
e[i][2]-=f;e[i^1][2]+=f;
sum+=f;minf-=f;
}
}
return sum;
}
bool check(long long limit)
{
build(limit);
int sumflow=0;
while(bfs())
{
sumflow+=dfs(0,inf);
}
if(sumflow==numcow)
return 1;
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&cow[i],&shelt[i]);
numcow+=cow[i]; sh+=shelt[i];
}
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
a[i][j]=10000000000000;
for(int i=0;i<=n;i++)
a[i][i]=0;
for(int j=1;j<=m;j++)
{
int temp1,temp2;
scanf("%d%d",&temp1,&temp2);
long long tempa;
scanf("%lld",&tempa);
if(a[temp1][temp2]>tempa)
{
a[temp1][temp2]=tempa;
a[temp2][temp1]=tempa;
if(a[temp1][temp2]>minmax)minmax=a[temp1][temp2]; //枚举上界
}
}
if(numcow>sh){printf("-1\n");return 0;} //无解情况
folyd();
long long left=0,right=minmax,mid;
if(!check(minmax)){printf("-1\n");return 0;} //无解情况
while(right>left+1) //二分答案,注意一下
{
mid=(right+left)/2;
if(check(mid))
{
right=mid;
}
else
left=mid;
}
if(check(right-1)) //最后二分时判断特殊情况
printf("%lld\n",right-1);
else
printf("%lld\n",right);
return 0;
}
POJ 2391 多源多汇拆点最大流 +flody+二分答案的更多相关文章
- POJ 3273-Monthly Expense 求分组和的最小的最大值【二分答案】
题目链接:http://poj.org/problem?id=3273 题目大意:给出一个有n个数据的数组,将其分为连续的m份,找到一种分法,是的m份中最大一份总和最小 解题思路: 直接在答案的区间内 ...
- poj 1698 Alice's Chance 拆点最大流
将星期拆点,符合条件的连边,最后统计汇点流量是否满即可了,注意结点编号. #include<cstdio> #include<cstring> #include<cmat ...
- poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap
poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...
- POJ 2391 Ombrophobic Bovines ★(Floyd+二分+拆点+最大流)
[题意]有n块草地,一些奶牛在草地上吃草,草地间有m条路,一些草地上有避雨点,每个避雨点能容纳的奶牛是有限的,给出通过每条路的时间,问最少需要多少时间能让所有奶牛进入一个避雨点. 和POJ2112很类 ...
- 2018.07.06 POJ 1459 Power Network(多源多汇最大流)
Power Network Time Limit: 2000MS Memory Limit: 32768K Description A power network consists of nodes ...
- POJ 2391 Ombrophobic Bovines ( 经典最大流 && Floyd && 二分 && 拆点建图)
题意 : 给出一些牛棚,每个牛棚都原本都有一些牛但是每个牛棚可以容纳的牛都是有限的,现在给出一些路与路的花费和牛棚拥有的牛和可以容纳牛的数量,要求最短能在多少时间内使得每头牛都有安身的牛棚.( 这里注 ...
- POJ 2391 floyd二分+拆点+最大流
Ombrophobic Bovines Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 20904 Accepted: 4 ...
- POJ 2391 容牛问题
题目大意:给定一个无向图,点i处有Ai头牛,点i处的牛棚能容纳Bi头牛,求一个最短时间T使得在T时间内所有的牛都能进到某一牛棚里去.(1 <= N <= 200, 1 <= M &l ...
- poj1459 Power Network (多源多汇最大流)
Description A power network consists of nodes (power stations, consumers and dispatchers) connected ...
随机推荐
- js dom node.children与node.childNodes区别
不同点:node.children不会取到节点下面的TextNode但是node.childNodes会取到 共同点:两者都是集合类数组,可以通过索引的方式取到值也可以用for循环遍历
- 使用colab运行深度学习gpu应用(Mask R-CNN)实践
1,目的 Google Colaboratory(https://colab.research.google.com)是谷歌开放的一款研究工具,主要用于机器学习的开发和研究.这款工具现在可以免费使用, ...
- windows系统下查看或删除自己电脑的共享文件以及文件夹
(1)查看所有共享 net share (2)删除指定共享 例如:删除C盘共享 net share C$ /delete net share 共享名 /delete (/del)
- 深入Docker 存储驱动 (转)
参考: http://static.dockerone.com/ppt/filedriver.html#28
- JavaScript轮播图
需求: 鼠标移动到下标页码时,也转换到相对应的图片: 多张图片可以自动轮播: 鼠标移动至图片时,停止自动轮播: 可以手动左右调节: <!DOCTYPE html> <html lan ...
- MATLAB读取每个文件夹下的badcsv文件后合并为总的badexcel文件
clear; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%读取子文件夹中bad.csv数据%并把所有数据写到一个excel文件中%%%%%%%%%%%%%%%%%% ...
- python 一些函数和类用法记录
这一篇主要用来记录在学习过程中遇到的一些觉得有意思的函数或者类的用法,有一些用法感觉很炫酷. 1.collections.defaultdict from collections import def ...
- 枚举为何不能设置成public?
听到测试与开发争论,为何枚举不能用public,用public怎么了?对于这个我也不知道到底能不能用,于是就去查了查资料. 解答: 枚举被设计成是单例模式,即枚举类型会由JVM在加载的时候,实例化枚举 ...
- docker守护式容器运行管理
docker守护式容器适合运行应用程序和服务 以交互方式进入容器 docker run -it centos /bin/bash 以交互方式进入 并设置镜像名称和运行后的主机名称 退出交互式容器并让 ...
- LeetCode(18)4Sum
题目 Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = ...