Southeast USA ICPC 2017 Security Badges(区间化点)

 

问题 H: Security Badges

时间限制: 2 Sec  内存限制: 128 MB
提交: 58  解决: 16
[提交][状态][讨论版][命题人:admin]

题目描述

You are in charge of the security for a large building. The building has a map, consisting of rooms, and doors between the rooms. Each door has a security code, which consists of a range of numbers, specified by a lower bound and an upper bound. Each employee has a uniquely numbered security badge. Only a security badge with a number within a door’s range can go through that door. 
Your boss wants a quick check of the security of the building. Given a starting room and a  destination  room,  how  many  security  badge  numbers  can  go  from  the  start  to  the destination?  

输入

Each input will consist of a single test case. Note that your program may be run multiple times on different inputs. Each test case will begin with a line containing three integers integer n (1 ≤ n ≤ 1,000), m (1 ≤ m ≤ 5,000) and k (1 ≤ k ≤ 109 ), where n is the number of rooms,  m  is  the  number  of  doors,  and  k  is  the  number  of  badges.  The  rooms  are numbered 1..n and the badges are numbered 1..k. 
The next line will contain two integers, s and d (1 ≤ s,d ≤ n), which indicate the starting room and destination room. 
Each of the next m lines will contain four integers, a, b (1 ≤ a,b ≤ n, a≠b), min and max (1 ≤ min ≤ max ≤ k) describing a door, where the door from room a to room b (and not back), and the badges range for the door is min..max, inclusive.  

输出

Output a single integer, which is the number of badges that can go from the start room to the destination room. 

样例输入

4 5 10
3 2
1 2 4 7
3 1 1 6
3 4 7 10
2 4 3 5
4 2 8 9

样例输出

5

提示

 

[提交][状态]

 

 

 

【题意】有n个顶点,m条有向边,每条边都有一个权值区间[l,r],表示只有在[l,r]之间的数才能够通过,给定一个k,和起始点s以及终点d,求出从s到d的一共可以通过多少数(1-k之间的数字可以通过的个数)

【思路】区间化点,对这些点进行排序,从小到大遍历,如果当前第i个的区间权值可以从s点到达d点,则第i+1也一定能够从s到达d;因为从s->d的路径权值区间最后求出来的一定是一个区间[l,r],而对于当前来说[i,i+1]区间来说就是最小的区间,一定符合题目要求。

【代码如下】

 

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5+10;
int n,m,k,s,d,cnt,head[N],vis[1100];
struct Edge{
    int v,next,l,r;
}edge[N];

void add(int u, int v, int l, int r){
    edge[cnt].v = v;
    edge[cnt].l = l;
    edge[cnt].r = r;
    edge[cnt].next = head[u];
    head[u] = cnt ++;
}

void dfs(int x, int id){
    if(vis[x]) return ;
    vis[x] = 1;
    for(int i = head[x]; ~i; i = edge[i].next){
        if(edge[i].l <= id && edge[i].r >= id) dfs(edge[i].v,id);
    }
}

int judge(int id){
    memset(vis,0,sizeof(vis));
    dfs(s,id);
    return vis[d];
}

int main(){
    while(~scanf("%d%d%d",&n,&m,&k)){
        scanf("%d%d",&s,&d);
        set<int>st;
        memset(head,-1,sizeof(head));
        cnt = 0;
        for(int i = 0; i < m; i ++){
            int u,v,l,r;
            scanf("%d%d%d%d",&u,&v,&l,&r);
            add(u,v,l,r);
            st.insert(l);
            st.insert(r+1);
        }
        int flag=0,last=0;
        set<int>::iterator it = st.begin();
        long long ans=0;
        for(; it != st.end(); it ++){
            if(flag) ans += (*it - last);
            flag = judge(*it);
            last = *it;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值