关闭

LightOJ 1167 - Dangerous Tunnels 二分枚举+最大流

240人阅读 评论(0) 收藏 举报
分类:

题目:http://www.lightoj.com/volume_showproblem.php?problem=1167


题意:山顶和山下分别有两个部落,编号为0和n+1,它们之间有很多隧道,有n个中转站(就是两条隧道相接的地方),每条隧道有一个危险程度,一条路径的危险程度是路径中所有隧道危险程度的最大值,几条路径的危险程度是危险程度最大的路径的危险程度,现在从山顶向山下选k条路径,求最大危险程度。选择隧道时只能从较高的中转站往较低的中转站走,且两条路径不能经过同一个中转站。


思路:中转站只能经过一次,所以拆点连边,容量为1,0和n + 1为源点汇点,为了方便一起拆点,容量设成一个较大值(本题大于等于10即可),然后我们二分枚举危险程度,小于等于枚举值的边连上,此时最大流的意义就是有几条路径,若大于等于k,说明枚举值是满足题意的,只要二分枚举到满足题意得最小值即可


总结:刚开始RE一发,后来忘写了换行,收获了WA。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;

const int N = 220;
const int INF = 0x3f3f3f3f;
typedef long long ll;
struct edge
{
    int to, cap, next;
}g[N*N*2];
int head[N], iter[N], level[N];
int n, m, cnt, _case = 0;
void add_edge(int v, int u, int cap)
{
    g[cnt].to = u, g[cnt].cap = cap, g[cnt].next = head[v], head[v] = cnt++;
    g[cnt].to = v, g[cnt].cap = 0, g[cnt].next = head[u], head[u] = cnt++;
}
bool bfs(int s, int t)
{
    memset(level, -1, sizeof level);
    level[s] = 0;
    queue<int> que;
    que.push(s);
    while(! que.empty())
    {
        int v = que.front(); que.pop();
        for(int i = head[v]; i != -1; i = g[i].next)
        {
            int u = g[i].to;
            if(g[i].cap > 0 && level[u] < 0)
            {
                level[u] = level[v] + 1;
                que.push(u);
            }
        }
    }
    return level[t] == -1;
}
int dfs(int v, int t, int f)
{
    if(v == t) return f;
    for(int &i = iter[v]; i != -1; i = g[i].next)
    {
        int u = g[i].to;
        if(g[i].cap > 0 && level[v] < level[u])
        {
            int d = dfs(u, t, min(g[i].cap, f));
            if(d > 0)
            {
                g[i].cap -= d, g[i^1].cap += d;
                return d;
            }
        }
    }
    return 0;
}
int dinic(int s, int t)
{
    int flow = 0, f;
    while(true)
    {
        if(bfs(s, t)) return flow;
        memcpy(iter, head, sizeof head);
        while(f = dfs(s, t, INF),f > 0)
            flow += f;
    }
}
int main()
{
    int t, k;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &m);
        int t1[N*N], t2[N*N], t3[N*N];
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d%d", t1 + i, t2 + i, t3 + i);
            if(t1[i] > t2[i]) swap(t1[i], t2[i]); //连边时从t1向t2连,要保证t1中转站高于t2对应中转站
        }
        scanf("%d", &k);
        int l = 0, r = 100001, res = -1;
        while(l <= r)
        {
            cnt = 0;
            memset(head, -1, sizeof head);
            int mid = (l + r) >> 1;
            for(int i = 1; i <= n; i++)
                add_edge(i, i + n + 2, 1); //对中转站拆点连边,容量1
            add_edge(0, 0 + n + 2, 10); //源点汇点拆点连边
            add_edge(n + 1, n + 1 + n + 2, 10);
            for(int i = 1; i <= m; i++)
                if(t3[i] <= mid) //小于等于枚举值连边
                    add_edge(t1[i] + n + 2, t2[i], 1);
            if(dinic(0, n + 1 + n + 2) >= k) r = mid - 1, res = mid;
            else l = mid + 1;
        }
        if(res == -1) printf("Case %d: no solution\n", ++_case);
        else printf("Case %d: %d\n", ++_case, res);
    }
    return 0;
}


0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

C陷阱篇之enum默认长度

enum型用于定义常量集合,相比#define有一些优势,如:enum是一种数据类型,使用时会检查类型匹配;enum增加了范围约束,避免变量赋值和使用时超出定义范围。但enum也有一个隐含问题:enu...
  • ipmux
  • ipmux
  • 2013-12-15 15:05
  • 7637

实例抓包分析USB鼠标枚举数据流 .

USB Monitor的高版本太复杂了,都不会用,这里还是使用2.5的老版本. 新建session,选择新插入的HID鼠标开始抓包,拔掉鼠标,清空记录,再次插入鼠标,现在就抓到了USB鼠标枚举数据流...
  • Luohsh1
  • Luohsh1
  • 2013-07-18 23:03
  • 5235

c++ 枚举的定义、设置值、取值范围

c++的  enum 工具提供了另一种创建符号常量的方式,这种方式可以代替  const。 他还允许定义新类型,但必须按严格的限制进行。使用enum  的用法与使用结构相似。 例如,请看下面的语句...
  • fengyelengfeng
  • fengyelengfeng
  • 2015-11-14 21:58
  • 2913

[最大流+二分答案] LightOJ 1167 - Dangerous Tunnels

1167 - Dangerous Tunnels 题意:一个图有n+2个点,m条边,其中0点是源点,n+1是汇点,其余的点是休息站,边只能从编号小的点指向编号大的点。 要从源点到汇点选择k条路,一...
  • kg20006
  • kg20006
  • 2016-04-07 20:34
  • 238

LightOJ 1156 - Jumping Frogs 二分枚举 + 最大流

题目:http://www.lightoj.com/volume_showproblem.php?problem=1156 题意:给定一段宽为m的河道,在河道中有n个石头排成一条直线,石头分两种:...
  • discreeter
  • discreeter
  • 2016-05-29 23:12
  • 334

[BZOJ1305][CQOI2009]dance跳舞(枚举二分+最大流)

思想需要经验的积累,灵感需要孤独的沉淀,最细致的体验需要最宁静透彻的观照。
  • Clove_unique
  • Clove_unique
  • 2016-05-02 17:35
  • 362

POJ 3189--Steady Cow Assignment【二分图多重匹配 && 最大流求解 && 枚举 && 经典】

Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6023   Acce...
  • hpuhjh
  • hpuhjh
  • 2015-08-27 13:10
  • 521

poj 2455 Secret Milking Machine(二分枚举+最大流)

题意: 题意:FJ有N块地,这些地之间有P条双向路,每条路的都有固定的长度l。现在要你找出从第1块地到第n块地的T条不同路径,每条路径上的路不能与先前的路径重复,问这些路径中的最长路的最小是多少...
  • hexianhao
  • hexianhao
  • 2016-07-29 15:07
  • 162

poj 2391 Ombrophobic Bovines(二分枚举+floyd+最大流+拆点)

Ombrophobic Bovines Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 127...
  • WEYuLi
  • WEYuLi
  • 2013-10-16 23:08
  • 546

【最大流+dinic+二分枚举】北大 poj 3189 Steady Cow Assignment

/* THE PROGRAM IS MADE BY PYY */ /*-----------------------------------------------------------------...
  • panyanyany
  • panyanyany
  • 2012-02-13 21:21
  • 635
    个人资料
    • 访问:152956次
    • 积分:7301
    • 等级:
    • 排名:第3531名
    • 原创:603篇
    • 转载:5篇
    • 译文:0篇
    • 评论:27条
    ~~~ACMER~~~
    最新评论