3500. 【NOIP2013模拟联考15】物语

Description

某一天,少年邂逅了同病相连的IA。见面后,IA一把牵起少年的手,决定和他一起逃离部落,离开这个无法容身的是非之地。

要逃离部落,少年和IA就需要先选择一条耗时最少的路线,从而避免被部落的大人们抓到。部落可以大致分为N个区域,少年和IA在区域1,部落的出口设在区域N。此外部落还有M条连接两个区域道路。道路是无向的,没有一条道路的两端连接相同的区域,也没有两条道路所连接的两个区域完全相同。对于其中前(M−1)条道路,其通过时间是确定的,但最后一条道路,由于地理因素,通过其的时间会不断变化。

现在,少年和IA得知了在K个不同的时段里,通过第M条道路的时间,请您分别计算出在这K 个时段中逃离部落的最少时间,以帮助他们确定行动的时刻。

Input

第一行三个整数N,M,K,分别表示区域数,道路数,询问数。

接下来M−1行每行三个整数ui,vi,wi(ui≠vi,1≤ui,vi≤N,0<wi≤10^9),表示这条道路连接的区域和通过时间。

紧接着是两个整数ui,vi(ui≠vi,1≤ui,vi≤N),表示第M条道路连接的区域。

最后K行,每行一个正整数xi(0<xi≤10^9),表示目前第M条道路的通过时间。

Output

输出共计K行,每行一个整数,表示对应时段逃离部落的最短时间。如果在该时段内无法逃离,输出“+Inf”。

Sample Input

输入1:

4 5 4

1 2 7

1 3 4

2 4 3

3 4 6

2 3

1

2

扫描二维码关注公众号,回复: 11489595 查看本文章

4

6

输入2:

4 3 1

1 2 7

1 3 4

2 3

9

Sample Output

输出1:

8

9

10

10

输出2:

+Inf

Data Constraint

Hint

Solution

方法一:从1和n开始分别跑一边最短路,那么对于最后一条边(x,y)答案就为min( dis[1~n],dis[1~x]+z+dis[y~n] ,dis[1~y]+len+dis[x~n] )

方法二:从1开始到n跑一边最短路,最小的路径有两种可能,1~n不经过len这条边,1~n经过len这条边,两个分开存,更新时,它们可以分别更新自己,其次,不经过最后一天边的可以通过最后一条边更新到经过这条边的最短路,那么最后的答案就是min(dis[ 不经过最后一条边 ][1~n]  ,dis[经过最后一条边][1~n]+len )。

注意最后一个数据点的范围不是最大的,其次spfa要用队首队尾玄学优化。

Code 1

#include<cstdio> 
#include<cstring>
#include<algorithm>
#define I int
#define ll long long
#define F(i,a,b) for(register I i=a;i<=b;++i)
#define Fd(i,a,b) for(register I i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof a)
#define N 200010
#define M 500000
using namespace std;
I n,m,k,x,y,z,i,j,bz[N],d[N<<3],t[M<<1],nx[M<<1],l[N],s[M<<1],tot;
ll f[2][N],inf;
void rd(I &x){
	x=0;char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
void A(I x,I y,I z){
	t[++tot]=y,nx[tot]=l[x],l[x]=tot,s[tot]=z;
}
void spfa(I z,I S){
	F(i,1,n) f[z][i]=1ll<<61;
	inf=f[z][1];
	f[z][d[1]=S]=0;
	i=1,j=1;
	while(i<=j){
		if(f[z][d[j]]<f[z][d[i]]) swap(d[i],d[j]);
		bz[x=d[i++]]=0;
		for(I k=l[x];k;k=nx[k]){
			y=t[k];
			if(f[z][y]>f[z][x]+(ll)s[k]){
				f[z][y]=f[z][x]+(ll)s[k];
				if(!bz[y]) bz[d[++j]=y]=1;
			}
		}
	}
}
I main(){
	rd(n),rd(m),rd(k);
	F(i,1,m-1){
		rd(x),rd(y),rd(z);
		A(x,y,z),A(y,x,z);
	}
	spfa(0,1);
	spfa(1,n);
	rd(x),rd(y);
	while(k--){
		rd(z);
		ll s=min(f[0][n],min(f[0][x]+f[1][y],f[0][y]+f[1][x])+z);
		if(s<inf){printf("%lld\n",s);}
		else printf("+Inf\n");
	}
	return 0;
}

Code2

#include<cstdio> 
#include<cstring>
#include<algorithm>
#define I int
#define ll long long
#define F(i,a,b) for(register I i=a;i<=b;++i)
#define Fd(i,a,b) for(register I i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof a)
#define N 200010
#define M 500000
using namespace std;
I n,m,k,x,y,z,bz[N],d[N<<3],t[M<<1],nx[M<<1],l[N],s[M<<1],tot;
ll f[2][N],inf;
void rd(I &x){
	x=0;char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}
void A(I x,I y,I z){t[++tot]=y,nx[tot]=l[x],l[x]=tot,s[tot]=z;}
I main(){
	rd(n),rd(m),rd(k);
	F(i,1,m-1){
		rd(x),rd(y),rd(z);
		A(x,y,z),A(y,x,z);
	}
	rd(x),rd(y);
	A(x,y,0),A(y,x,0);
	F(i,2,n) f[0][i]=f[1][i]=1ll<<62;
	inf=f[d[1]=1][2];
	I i=1,j=1;
	while(i<=j){
		if(f[1][d[j]]<f[1][d[i]]) swap(d[i],d[j]);
		bz[x=d[i++]]=0;
		for(I k=l[x];k;k=nx[k]){
			y=t[k];
			if(s[k]){
				F(z,0,1) if(f[z][y]>f[z][x]+s[k]){
					f[z][y]=f[z][x]+s[k];
					if(!bz[y]) bz[d[++j]=y]=1;
				}
			}
			if(!s[k]){
				if(f[0][y]>f[1][x]+s[k]){
					f[0][y]=f[1][x]+s[k];
					if(!bz[y]) bz[d[++j]=y]=1;
				}
			}
		}
	}
	while(k--){
		rd(z);
		if(f[0][n]+z<inf||f[1][n]<inf){printf("%lld\n",min(f[0][n]+z,f[1][n]));}
		else printf("+Inf\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zsjzliziyang/article/details/104199523