51Nod 1326 遥远的旅途

题目描述:
一个国家有N个城市,这些城市被标为0,1,2,...N-1。这些城市间连有M条道路,每条道路连接两个不同的城市,且道路都是双向的。一个小鹿喜欢在城市间沿着道路自由的穿梭,初始时小鹿在城市0处,它最终的目的地是城市N-1处。小鹿每在一个城市,它会选择一条道路,并沿着这条路一直走到另一个城市,然后再重复上述过程。每条道路会花费小鹿不同的时间走完,在城市中小鹿不花时间逗留。路程中,小鹿可以经过一条路多次也可以经过一个城市多次。给定城市间道路的信息,问小鹿是否有一种走法,从城市0出发到达城市N-1时,恰好一共花费T个单位的时间。如果存在输出“Possible”,否则输出“Impossible”。
注意,小鹿在整个过程中可以多次经过城市N-1,只要最终小鹿停在城市N-1即可。
例如样例中小鹿的行程可以是0->1->2->0->2.

解题报告:
用时:1h30min,1TLE
这题首先要明白,到终点至少要经过一条n的出边,所以如果可行,一定是将某一条出边走很多次,然后再到达终点,即 \(2*w+j==T\),所以只要 \(j=T\mod2*w\) 存在即可,所以我们枚举每一条出边,然后跑spfa ,看 \(f[n][j]\) 是否存在即可,我们定义 \(f[i][j]\) 表示到达了\(i\)这个点 走过的距离\(s \mod2*w\)\(j\)的最小时间,因为要保证到达n后时间\(\leq T\),所以我们要使得\(f[n][j]\)尽量小,做spfa即可

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=55,M=1000005;
int q[M][2],mod=M,n,m,head[N],to[N<<1],dis[N<<1],nxt[N<<1],num=0,mo;
ll TT,f[N][20005];bool vis[N][20005];
void link(int x,int y,int z){
	nxt[++num]=head[x];to[num]=y;dis[num]=z;head[x]=num;
}
void spfa(){
	int x,u,disp,t=0,sum=1,now;q[sum][0]=1;q[1][1]=0;
	memset(vis,0,sizeof(vis));vis[1][0]=true;
	memset(f,127/3,sizeof(f));f[1][0]=0;
	while(t!=sum){
		t++;if(t==mod)t=0;x=q[t][0];now=q[t][1];
		if(f[n][TT%mo]<=TT)return ;
		for(int i=head[x];i;i=nxt[i]){
			u=to[i];
			disp=(now+dis[i])%mo;
			if(f[x][now]+dis[i]<f[u][disp]){
				f[u][disp]=f[x][now]+dis[i];
				if(!vis[u][disp]){
					vis[u][disp]=true;sum++;if(sum==mod)sum=0;
					q[sum][0]=u;q[sum][1]=disp;
				}
			}
			vis[x][now]=false;
		}
	}
}
void Clear(){
	memset(head,0,sizeof(head));num=0;
}
void work()
{
	Clear();
	int x,y,z;
	cin>>n>>m>>TT;
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&x,&y,&z);
		x++;y++;link(x,y,z);link(y,x,z);
	}
	for(int i=head[n];i;i=nxt[i]){
		mo=dis[i]<<1;
		spfa();
		if(f[n][TT%mo]<=TT){
			puts("Possible");
			return ;
		}
	}
	puts("Impossible");
}

int main()
{
	int T;cin>>T;
	while(T--)work();
	return 0;
}

posted @ 2017-09-24 20:21  PIPIBoss  阅读(134)  评论(0编辑  收藏  举报