poj 1613 Cave Raider

Cave Raider
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 870   Accepted: 268

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
*

这是一道好题啊,没有直接考最短路,而是加了一些限制条件,间接来考最短路。由于每个通道都有开闭的时间区间,我们用一个vector来存储时间点,按照奇偶来分该段时间区间是否为开放时段。假设我们要从一个通道的v端,通向u端,而已知所需时间为t,那么现在我们考虑到达v的时间点为tv,这个时候通道可能处于关闭状态,当然也可能处于开放状态,我们用t[k-1]->t[k]来表示开放时间,那么如果tv<t[k-1],我们自然要等到t[k-1]才能进通道,而如果t[k]>tv>t[k-1],那么我们就可以直接进入通道,由此发现进入通道的时间为T=max(tv,t[k-1]),当然进入通道时有时间限制的,如果t[k]-T<t,那么我们是不能进入的,否则还没出来,通道就会关闭,然后你就被“清理”了。

但这道题目和最短路有关系吗?我们来想想bellman-ford的算法,松弛n-1次就得到源点到其他点的最短路,在算法中松弛是按照其他点到源点路径边数增加方向进行的。那么我们也可以将一个通道看成一条边,第一次松弛显然会得到距离源点边数为1的最短路,之后可以想象继续松弛,就和算最短路思想是一致的。

那么我们是否可以用dijkstra算法呢?答案是显然可以,只不过我们经过每个通道的时间必须按照上述列的规则计算,同样算法的正确性可以类比dijkstra的算法的证明思路。


代码:

#include<cstdio>
#include<iostream>
#include<vector>
#define Maxn 510
using namespace std;

struct line{
    int u,v,w;
    vector<int> dv;
    line(){}
    line(int uu,int vv,int ww):u(uu),v(vv),w(ww){dv.clear();}
}p[Maxn];
int dist[60];
char str[1000];
const int inf=1<<30;
void bellman(int r,int n,int m,int e){
    for(int i=1;i<=n;i++)
        dist[i]=inf;
    dist[r]=0;
    for(int i=1;i<n;i++)
        for(int j=0;j<m;j++){
            int u=p[j].u,v=p[j].v,w=p[j].w;
            for(int k=1;k<p[j].dv.size();k++){
                bool flag=k&1?true:false;
                int maxt=max(dist[u],p[j].dv[k-1]);
                if(flag&&maxt+w<=p[j].dv[k]&&maxt+w<dist[v]){
                    dist[v]=maxt+w;break;
                }
            }
        }
    if(dist[e]==inf) puts("*");
    else printf("%d\n",dist[e]);
}
int main()
{
    int n,m,s,e,u,v,w;
    while(scanf("%d",&n),n){
        scanf("%d%d%d",&m,&s,&e);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&u,&v,&w);
            p[i]=line(u,v,w);
            p[i].dv.push_back(0);
            gets(str);
            int base=0;
            for(int j=0;str[j];j++){
                if(isdigit(str[j])) base=base*10+str[j]-'0';
                else if(base){p[i].dv.push_back(base);base=0;}
            }
            if(base) p[i].dv.push_back(base);
            p[i].dv.push_back(inf);
            p[i+m]=p[i],p[i+m].u=v,p[i+m].v=u;
        }
        bellman(s,n,m<<1,e);
    }
	return 0;
}


你可能感兴趣的:(poj 1613 Cave Raider)