问题 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;
}