POJ-1613 Cave Raider

14 篇文章 0 订阅
Cave Raider
Time Limit: 1000MS Memory Limit: 10000K

Description

Afkiyia is a big mountain. Inside the mountain, there are many caves. These caves are connected by tunnels. Hidden in one of the caves is a terrorist leader. Each tunnel connects two caves. There could be more than one tunnels connect the same two caves.
At the joint of a tunnel and a cave, there is a door. From time to time, the terrorists close a tunnel by shutting the two doors at the two ends, and "clean" the tunnel. It is still a mystery how they clean the tunnel. However, we know that if a person (or any living creature) is trapped in the tunnel when it is being cleaned, then the person (or the living creature) will die. After a cleaning of the tunnel is finished, the door will open, and the tunnel can be used again.
Now the intelligence servicemen have found out which cave the leader is hiding,and moreover, they know the schedule of the cleaning of the tunnels. Jing Raider is going to go into the cave and catch the leader. You need to help him find a route so that he can get to that cave in the shortest time. Be careful not to be trapped in a tunnel when it is being cleaned.

Input

The input consists of a number of test cases. The 1st line of a test case contains four positive integers n,m, s, t, separated by at least one space, where n is the number of caves (numbered 1, 2, ... , n), m is the number of tunnels (numbered 1, 2, ... ,m), s is the cave where Jing is located at time 0, and t is the cave where the terrorist leader is hiding. (1 <= s, t <= n <= 50 and m <= 500).
The next m lines are information of the m tunnels: Each line is a sequence of at most 35 integers separated by at least one space. The first two integers are the caves that are the ends of the corresponding tunnel. The third integer is the time needed to travel from one end of the tunnel to the other. This is followed by an increasing sequence of positive integers (each integer is at most 10000) which are alternately the closing and the opening times of the tunnel. For example, if the line is
10 14 5 6 7 8 9
then it means that the tunnel connects cave 10 and cave 14, it takes 5 units of time to go from one end to the other. The tunnel is closed at time 6, opened at time 7, then closed again at time 8, opened again at time 9. Note that the tunnel is being cleaned from time 6 to time 7, and then cleaned again from time 8 to time 9. After time 9, it remains open forever.
If the line is
10 9 15 8 18 23
then it means that the tunnel connects cave 10 and cave 9, it takes 15 units of time to go from one end to the other. The tunnel is closed at time 8, opened at time 18,then closed again at time 23. After time 23, it remains closed forever.
The next test case starts after the last line of the previous case. A 0 signals the end of the input.

Output

The output contains one line for each test case. Each line contains either an integer, which is the time needed for Jing to get to cave t, or the symbol *, which means that Jing can never get to cave t. Note that the starting time is 0. So if s = t, i.e., Jing is at the same cave as the terrorist leader, then the output is 0.

Sample Input

2 2 1 2
1 2 5 4 10 14 20 24 30
1 2 6 2 10 22 30
6 9 1 6
1 2 6 5 10
1 3 7 8 20 30 40
2 4 8 5 13 21 30
3 5 10 16 25 34 45
2 5 9 22 32 40 50
3 4 15 2 8 24 34
4 6 10 32 45 56 65
5 6 3 2 5 10 15
2 3 5 2 9 19 25
2 2 1 2
1 2 7 6 9 12
1 2 9 8 12 19
0

Sample Output

16
55
*
————————————————————集训13.1的分割线————————————————————

前言:这真是一道丧心病狂的题目。写了一天。首先有几点需要注意:

1. 测试数据的输入有问题,貌似不仅仅是一个空格。需要对时间表长度未知的那一行特殊处理(模拟读数)

2. 这题连样例都说明了有重边

3. 无向图

思路:限制最短路。首先看到边的个数少于500,那么邻接表。求单源最短路,那么用SPFA最好了。有一个时间表需要存进结构体,用来判断每个边在什么时刻能够访问。时间表大小不定,需要先gets,然后模拟一下。技巧:应用vector来储存这种未知长度的数组。(题目先给关闭时刻,后给打开时刻,可以在表头插一个0,末尾插一个INF,会方便很多)

读完之后,跑一遍spfa。使用队列中的元素进行松弛操作,注意!遍历时间表,直到判定能够在该边关闭之前到达下个点,然后松弛、break。

怎样判定是否能在关闭之前通过洞穴呢?如果dis[u]小于洞穴开启时刻,说明要等待开启,如果开启要计算会不会被“清理”,一旦能,就尝试松弛。

代码如下:

/*
ID: j.sure.1
PROG:
LANG: C++
 */
/****************************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <climits>
#include <iostream>
#define INF 0x3f3f3f3f
using namespace std;
/****************************************/
const int N = 55, M = 505;
int n, m, tot;  
int dis[N], head[N];
bool inq[N];
struct Node 
{  
	int u, v, w, next;
	vector <int> table;
}G[M*2];

int spfa(int st, int ed)  
{  
	memset(dis, 0x3f, sizeof(dis));
	memset(inq, 0, sizeof(inq));
	queue <int> q;
	dis[st] = 0;
	inq[st] = true;
	q.push(st);
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		inq[u] = false;
		for(int cur = head[u]; cur != -1; cur = G[cur].next) {
			Node &cave = G[cur];
			int v = cave.v, w = cave.w;
			int siz = cave.table.size();//遍历时间表
			for(int k = 1; k < siz; k+=2) {//奇数是关闭
				int &on = cave.table[k-1], &off = cave.table[k];
				int cost = dis[u] > on ? dis[u] : on;
				if(cost + w <= off) {//如果能在关闭之前到达
					if(dis[v] > cost + w) {//松弛操作
						dis[v] = cost + w;  
						if(!inq[v]) {  
							inq[v] = true;  
							q.push(v);
						}
					}
					break;  
				}  
			}  
		}  
	}  
	return dis[ed];
}  

int main() 
{  
#ifdef J_Sure
	freopen("000.in", "r", stdin);
//  freopen(".out", "w", stdout);
#endif  
	int st, ed;
	while(scanf("%d", &n), n) {  
		scanf("%d%d%d", &m, &st, &ed);  
		tot = 0;
		memset(head, -1, sizeof(head));
		int u, v, w;  
		char s[1001];  
		int time_table[1001];  
		while(m--) {
			scanf("%d%d%d", &u, &v, &w);	
			gets(s);
			int cal = 0, num = 0;  
			for(int i = 0; i <= strlen(s); i++) {  
				if(s[i] >= '0' && s[i] <= '9')
					cal = cal*10 + s[i] - '0';  
				else if(cal) {
					time_table[num++] = cal;
					cal = 0;
				}
			}
			Node now;  
			now.w = w;  
			now.table.push_back(0);//开始时间是0
			for(int i = 0; i < num; i++) {
				now.table.push_back(time_table[i]);//读入时间表
			}
			now.table.push_back(INF);
			G[tot].u = u; G[tot].v = v; G[tot].w = w;
			G[tot].table = now.table; G[tot].next = head[u]; head[u] = tot++;
			G[tot].u = v; G[tot].v = u; G[tot].w = w;
			G[tot].table = now.table; G[tot].next = head[v]; head[v] = tot++;
		}  
		int ans = spfa(st, ed);
		if(ans >= INF)
			puts("*");
		else
			printf("%d\n", ans);
	}
	return 0;	
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值