题意:

      有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的更多相关文章

  1. poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap

    poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...

  2. [Codeforces 1199C]MP3(离散化+二分答案)

    [Codeforces 1199C]MP3(离散化+二分答案) 题面 给出一个长度为n的序列\(a_i\)和常数I,定义一次操作[l,r]可以把序列中<l的数全部变成l,>r的数全部变成r ...

  3. Optimal Milking(POJ2112+二分+Dinic)

    题目链接:http://poj.org/problem?id=2112 题目: 题意:有k台挤奶机,c头奶牛,每台挤奶机每天最多生产m的奶,给你每个物品到其他物品的距离(除了物品到自己本省的距离为0外 ...

  4. hdu 4400 离散化+二分+BFS(暴搜剪枝还超时的时候可以借鉴一下)

    Mines Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...

  5. POJ 3189 二分+Dinic

    题意: 思路: 二分跨度 枚举最低座次 建图:源点向每头牛连边权为1的边 每头牛向当前枚举的B的区间这段连上边权为1的边 所有座次向汇点连边权为牛棚容量的边 判判流量是不是等于n 一开始写得是直接枚举 ...

  6. 2019 Multi-University Training Contest 3 Find the answer (离散化+二分+树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6609 题目大意:给定一个含有n个数的序列,还有一个m,对于每个i(1<=i<=n)求出最少 ...

  7. 2019牛客暑期多校训练营(第七场)E-Find the median(思维+树状数组+离散化+二分)

    >传送门< 题意:给n个操作,每次和 (1e9范围内)即往数组里面插所有 的所有数,求每次操作后的中位数思路:区间离散化然后二分答案,因为小于中位数的数字恰好有个,这显然具有单调性.那么问 ...

  8. Codeforces Round #521 (Div. 3) E. Thematic Contests (离散化,二分)

    题意:有\(n\)个话题,每次都必须选取不同的话题,且话题数必须是上次的两倍,第一次的话题数可以任意,问最多能选取多少话题数. 题解:我们首先用桶来记录不同话题的数量,因为只要求话题的数量,与话题是多 ...

  9. nyoj-310-河南省第四届省赛题目-二分+dinic

    SECRET 时间限制:3000 ms  |  内存限制:65535 KB 难度:6   描述 Dr.Kong is constructing a new machine and wishes to ...

随机推荐

  1. 25个关键技术点,带你熟悉Python

    摘要:本文收纳了Python学习者经常使用的库和包,并介绍了Python使用中热门的问题. 01.Python 简介 什么是 Python 一种面向对象的高级动态可解释型脚本语言. Python 解释 ...

  2. 2020年12月-第02阶段-前端基础-CSS字体样式

    CSS字体样式属性调试工具 应用 使用css字体样式完成对字体的设置 使用css外观属性给页面元素添加样式 1.font字体 1.1 font-size:大小 作用: font-size属性用于设置字 ...

  3. 冒泡算法及其优化(java)

    冒泡算法的规则: 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放待排序序列的起始位置(或末尾位置),直到全部待排序的数据元素排完 动态图: 对应代码 static void swap(i ...

  4. Azure AD, Endpoint Manger(Intune), SharePoint access token 的获取

    本章全是干货,干货,干货,重要的事情说三遍. 最近在研究Azure, Cloud相关的东西,项目中用的是Graph API(这个在下一章会相信介绍),可能是Graph API推出的时间比较晚,部分AP ...

  5. C# 应用 - 多线程 7) 处理同步数据之 Synchronized code regions (同步代码区域): Monitor 和 lock

    目录: System.Threading.Monitor:提供同步访问对象的机制; lock 是语法糖,是对 Monitor Enter 和 Exit 方法的一个封装 lock 案例 1. Monit ...

  6. 使用css3和javascript开发web拾色器实例

    本实例中的web拾色器功能使用css3实现页面效果,即在页面上显示的元素用css3样式来实现的.再使用js生成拾色器颜色数据,并控制各元素的鼠标事件.当事件作为反应时,获取到对应的数据并显示颜色值. ...

  7. 2019 GDUT Rating Contest III : Problem D. Lemonade Line

    题面: D. Lemonade Line Input file: standard input Output file: standard output Time limit: 1 second Memo ...

  8. 自然语言处理(NLP)知识结构总结

    自然语言处理知识太庞大了,网上也都是一些零零散散的知识,比如单独讲某些模型,也没有来龙去脉,学习起来较为困难,于是我自己总结了一份知识体系结构,不足之处,欢迎指正.内容来源主要参考黄志洪老师的自然语言 ...

  9. 让JS代码Level提升的忍者秘籍(实用)

    本文章共2377字,预计阅读时间5-10分钟. 前言 没有前言. 你准备好成为同事眼中深藏不露.高深莫测.阳光帅气的前端开发了吗? 那就开始吧! 本文秉承宗旨:代码实用与逼格并存. 提升JS代码Lev ...

  10. 计算机图形学中使用Turbo C++画图步骤

    一.下载安装Turbo C++ 我安装的是Turbo C++ 3.2.2.0下载链接 二.画图 1.打开Turbo C++,点击右下角start turbo C++ 2.点击file ->new ...