逃离 单源最短路

逃离

Problem Description
遥远的delta星球上,第4次世界大战的战火迅速燃遍各地。X国前哨站的部队成功获取敌方的作战计划,得知敌方将对前哨战及周边的道路进行轰炸,部队必须立即撤回基地。由于空军很忙,部队只能从走陆路。
前哨站与基地间有n个中转站和m条双向道路,已知敌军对每条路开始实行轰炸的时刻(若某条道路将在第x秒开始被轰炸,则部队在第x秒及x秒以后不能处在该道路上),以及通过每条道路所需时间。若部队从第0秒出发,请你计算出部队安全回到基地所需的最少时间。若无法安全逃离,则输出-1。
Input
第一行两个正整数n和m,分别表示中转站个数和道路数,之间用一个空格隔开。
接下来m行,每行四个正整数x,y,t1,t2,之间用一个空格隔开,表示中转站x与中转站y之间(前哨站用0表示,基地用n+1表示)有一条双向道路,该道路通过所需时间为t1秒,将在第t2秒开始被轰炸。
Output
输出一个整数,为部队安全回到基地所需的最少时间。若无法安全逃离,则输出-1。
Sample Input
2 5
0 1 3 3
0 2 2 1
1 2 1 5
1 3 4 10
2 3 2 6
Sample Output
6
Data Instraint
对于30%的数据,有n≤5,m≤20;
对于50%的数据,有n≤50,m≤500;
对于100%的数据,有n≤1,000,m≤500,000,所有时间、时刻在longint范围内,保证结果在longint范围内。

观察本题,很显然,这道题是一道单源最短路。题目询问我们,从点0到点n+1所花费的最少时间是多少,并且,它的路径多了一个毁灭时间作为限制。也就是说,已知到点i的最短时间 d[i],对于路所花费时间t1,毁灭时间t2,如果有d[i]+t1≤t2,那么,这条边就是可以使用的。而如果d[i]+t1>t2,则此边在这时是无效的。所以,这仅仅是多了一个对边是否有效进行判断,跑一遍SPFA,就可以得到答案了。
那么,我们就可以写出了如下代码。

#include 
#include 

using namespace std;

int n,m,tot;
int h[1010],d[1010];
bool in[1010];
struct edge{
	int next,to,value,destroy;
}e[1000010];
int q[100010],head=1,tail=1;

inline int read()
{
	int x=0;char c=getchar();
	while ((c<'0')||(c>'9'))
		c=getchar();
	while ((c>='0')&&(c<='9'))
		x=(x<<3)+(x<<1)+c-'0',c=getchar();
	return x;
}

void spfa();

int main()
{
	freopen("escape.in","r",stdin);
	freopen("escape.out","w",stdout);
	n=read();m=read();
	for (int i=1;i<=m;i++)
	{
		int a,b,c,d;
		a=read();b=read();c=read();d=read();
		e[++tot]=(edge){h[a],b,c,d};h[a]=tot;
		e[++tot]=(edge){h[b],a,c,d};h[b]=tot;
	}
	memset(d,-1,sizeof d);
	d[0]=0;in[0]=true;
	spfa();
	printf("%d",d[n+1]);
	return 0;
}

void spfa()
{
	while (head<=tail)
	{
		int now=q[head++];
		in[now]=false;
		for (int jump=h[now];jump;jump=e[jump].next)
		{
			int t=e[jump].to;
			if (e[jump].value+d[now]>e[jump].destroy)
				continue;			
			if (((d[t]!=-1)&&(e[jump].value+d[now]>=d[t])))
				continue;
			d[t]=e[jump].value+d[now];
			if (!in[t])
				q[++tail]=t,in[t]=true;
		}
	}
	return ;
}

你可能感兴趣的:(逃离 单源最短路)