POJ2391 Floyd+离散化+二分+DINIC
题意:
有n个猪圈,每个猪圈里面都有一定数量的猪(可能大于当前猪圈的数量),每个猪圈都有自己的容量,猪圈与猪圈之间给出了距离,然后突然下雨了,问多久之后所有的猪都能进圈。
思路:
先跑一遍Floyd求出任意两点之间的最短距离,对于时间,也就是答案,我们可以二分去找,然后对于每次二分,我们可以用DINIC去判断是否满足要求,建图的时候记得拆点,一开始我感觉不用抄点,但是都敲完了,发现不行,又重新建图了,拆成二分图,然后根据当前二分的值连边。。。这个题比较简单,没啥难点,就是长时间没写了,练练手,还有提醒一点,二分的时候可以不直接二分时间,我们可以吧所有可能的时间都找出来,排序,离散化一下,这样直接二分下标,减少时间开销(直接不离散化目测也行,但是离散化能更快点)。下面是我的代码,用的方法是 Floyd+离散化+二分+DINIC做的,这个题思路不难,就是练练手,就解释这么多。
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N_node 400 + 10
#define N_edge (200 * 200 + 400) * 2 + 100
#define INF 2000000000
#define III 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef struct
{
int to ,cost ,next;
}STAR;
typedef struct
{
int x ,t;
}DEP;
DEP xin ,tou;
STAR E[N_edge];
int list[N_node] ,listt[N_node] ,tot;
int deep[N_node];
long long map[202][202];
long long tmp[50000] ,num[50000];
int L[202] ,R[202];
int S;
void add(int a ,int b ,int c)
{
E[++tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot;
E[++tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
}
int minn(int x ,int y)
{
return x < y ? x : y;
}
void Floyd(int n)
{
for(int k = 1 ;k <= n ;k ++)
for(int i = 1 ;i <= n ;i ++)
for(int j = 1 ;j <= n ;j ++)
if(map[i][j] > map[i][k] + map[k][j])
map[i][j] = map[i][k] + map[k][j];
}
bool BFS_Deep(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
deep[s] = 0;
xin.x = s ,xin.t = 0;
queue<DEP>q;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
listt[i] = list[i];
return deep[t] != -1;
}
int DFS_Flow(int s ,int t ,int flow)
{
if(s == t) return flow;
int nowflow = 0;
for(int k = listt[s] ;k ;k = E[k].next)
{
listt[s] = k;
int to = E[k].to;
int c = E[k].cost;
if(deep[to] != deep[s] + 1 || !c)
continue;
int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow));
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(flow == nowflow) break;
}
if(!nowflow) deep[s] = 0;
return nowflow;
}
int DINIC(int s ,int t ,int n)
{
int Ans = 0;
while(BFS_Deep(s ,t ,n))
{
Ans += DFS_Flow(s ,t ,INF);
}
return Ans;
}
void Buid(int n ,long long mid)
{
memset(list ,0 ,sizeof(list)) ,tot = 1;
for(int i = 1 ;i <= n ;i ++)
add(0 ,i ,L[i]) ,add(i + n ,n + n + 1 ,R[i]);
for(int i = 1 ;i <= n ;i ++)
for(int j = 1 ;j <= n ;j ++)
if(map[i][j] <= mid) add(i ,j + n ,INF);
}
long long solve(int n)
{
int t = 0;
for(int i = 1 ;i <= n ;i ++)
for(int j = i ;j <= n ;j ++)
if(map[i][j] != III) tmp[++t] = map[i][j];
sort(tmp + 1 ,tmp + t + 1);
int numn = 0;
for(int i = 1 ;i <= t ;i ++)
if(i == 1 || tmp[i] != tmp[i-1])
num[++numn] = tmp[i];
int low = 1 ,up = numn ,mid;
long long Ans = -1;
while(low <= up)
{
mid = (low + up) >> 1;
Buid(n ,num[mid]);
if(DINIC(0 ,n + n + 1 ,n + n + 1) == S)
{
Ans = num[mid];
up = mid - 1;
}else low = mid + 1;
}
return Ans;
}
int main ()
{
int n ,m ,i ,j;
long long a ,b ,c;
while(~scanf("%d %d" ,&n ,&m))
{
for(S = 0 ,i = 1 ;i <= n ;i ++)
{
scanf("%d %d" ,&L[i] ,&R[i]);
S += L[i];
}
for(i = 1 ;i <= n ;i ++)
{
for(j = i + 1;j <= n ;j ++)
map[i][j] = map[j][i] = III;
map[i][i] = 0;
}
for(i = 1 ;i <= m ;i ++)
{
scanf("%lld %lld %lld" ,&a ,&b ,&c);
if(map[a][b] > c) map[a][b] = map[b][a] = c;
}
Floyd(n);
long long Ans = solve(n);
printf("%lld\n" ,Ans);
}
return 0;
}
POJ2391 Floyd+离散化+二分+DINIC相关推荐
- POJ - 3179 Corral the Cows(离散化+二分+二维前缀和)
题目链接:点击查看 题目大意:在二维平面中给出n个点,每个位置都有一个一个三叶草,现在需要求出一个长方形区域,要求长方形边长最短,并且面积内部包含至少C个三叶草 题目分析:题目给出的n最大为500,但 ...
- POJ 3179Corral the Cows(离散化+二分)
题目链接: http://poj.org/problem?id=3179 题意: 有一个最大为10000的图,里面有一些特定的点叫三叶草,每个这样的点可包括往上.右.右上(也就是这是单位矩形的左下角) ...
- POJ3179 Corral the Cows 离散化 二分 前缀和
题目链接 http://poj.org/problem?id=3179 分析 容易想到二分和前缀和,难点在于坐标离散化,要将横纵坐标分别离散化. 对于三叶草的每个坐标,将其映射为次序: 没有三叶草的位 ...
- 【codevs1422】河城荷取 二分+dinic
题目描述 Description 在幻想乡,河城荷取是擅长高科技工业的河童.荷取的得意之作除了光学迷彩外,还有震动整个幻想乡的巨型人形『非想天则』.不过由于人形太过巨大,所以为它充能是一件很麻烦的事. ...
- Gym - 100519 B Bring Your Own Bombs 离散化+二分+思维
题目链接:https://vjudge.net/contest/370255#problem/B 我们考虑每一行每一列会爆炸的概率是多少 显然 对于会爆炸的每一行 位于该行的矩形的长都会爆炸 对于 ...
- POJ 2391 Ombrophobic Bovines ★(Floyd+二分+拆点+最大流)
[题意]有n块草地,一些奶牛在草地上吃草,草地间有m条路,一些草地上有避雨点,每个避雨点能容纳的奶牛是有限的,给出通过每条路的时间,问最少需要多少时间能让所有奶牛进入一个避雨点. 和POJ2112很类 ...
- [总结]2019年9月 OI学习/刷题记录
从现在开始记录一下每天的学习情况.主力LOJ? 2019/9/5 LibreOJ #2543. 「JXOI2018」排序问题 答案显然是\(\frac{(n+m)!}{Cnt_1!Cnt_2!\cdo ...
- 题解 P1682 【过家家】
P1682 过家家 题目描述 有2n个小学生来玩过家家游戏,其中有n个男生,编号为1到n,另外n个女生,编号也是1到n.每一个女生可以先选择一个和她不吵嘴的男生来玩,除此之外,如果编号为X的女生的朋友 ...
- Codeforces Global Round 2 D. Frets On Fire (动态开点线段树,沙雕写法)
题目链接:D. Frets On Fire 思路:明明可以离散化+二分写,思路硬是歪到了线段树上,自闭了,真实弟弟,怪不得其他人过得那么快 只和查询的区间长度有关系,排完序如果相邻的两个点的差值小于等 ...
最新文章
- 学习Exchange管理最佳实践
- hdu 1280用hash解决。。
- 文本聊天室(TCP-中)
- 100个最古老互联网域名 最久只有23年(附名单)
- 自学Python:截取屏幕画面
- Yocto tips (17): Yocto License问题:restricted license not whitelisted in LICENSE_FLAGS_WHITELIST
- 生成xml_freemarker快速生成xml文件
- 马尔可夫随机场数学原理理解
- 一次网站登录慢故障排查
- ios的Navigation Controller的学习使用
- 物体检测算法:R-CNN,SSD,YOLO 动手学深度学习v2 pytorch
- 如何连接linux服务器
- QTP软件测试工具学习
- 液压系统仿真软件_利用仿真软件判断系统稳定
- Windows10系统把JDK安装到D盘上的步骤及安装
- DBeaver复制数据库报错@@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLO
- 3.3V的稳压管,结果电压变成了2.5V
- 微信隐藏功能:群接龙
- 怀揣梦想,我依靠自己,往后余生越来越精彩
- 问题 D: 猫和兔子
热门文章
- 百篇大计敬本年之系统篇《八》—— Ubuntu16.04 挂载windows的 NTFS 文件系统时错误的解决方法...
- [Android Pro] InputStream.skip方法的思考
- 30个最常用css选择器解析
- 给你的Flex程序添加深链接和分析-其实比你想象的要简单
- [原创].NET 业务框架开发实战之十 第一阶段总结,深入浅出,水到渠成(前篇)...
- 极虎病毒创造四个“之最”
- Tomcat的manager APP设置
- iptables日志探秘
- hdu5643 King's Game(约瑟夫环+线段树)
- 【mysql】关于事务的隔离级别