模拟赛 长途旅行(时间限制:1s;空间限制:256M)

题目描述

JY是一个爱旅游的探险家,也是一名强迫症患者。现在JY想要在C国进行一次长途旅行,C国拥有n个城市(编号为0,1,2...,n - 1),城市之间有m条道路,可能某个城市到自己有一条道路,也有可能两个城市之间有多条道路,通过每条道路都要花费一些时间。JY从0号城市开始出发,目的地为n – 1号城市。由于JY想要好好参观一下C国,所以JY想要旅行恰好T小时。为了让自己的旅行更有意思,JY决定不在任何一个时刻停留(走一条到城市自己的路并不算停留)。JY想知道是否能够花恰好T小时到达n – 1号城市(每个城市可经过多次)。现在这个问题交给了你。
若可以恰好到达输出“Possible”否则输出“Impossible”。(不含引号)。

输入格式

第一行一个正整数Case,表示数据组数。
每组数据第一行3个整数,分别为n, m, T。
接下来m行,每行3个整数x, y, z,代表城市x和城市y之间有一条耗时为z的双向边。

输出格式

对于每组数据输出”Possible”或者”Impossible”.

样例输入

2
3 3 11
0 2 7
0 1 6
1 2 5
2 1 10000
1 0 1

样例输出

Possible
Impossible


样例解释

第一组:0 -> 1 -> 2 :11
第二组:显然偶数时间都是不可能的。


数据范围

30%: T <= 10000
另有30%: n <= 5 , m <= 10.
100%: 2 <= n <= 50 , 1 <= m <= 100 , 1 <= z <= 10000 , 1 <= T <= 10^18 , Case <= 5.

题解

最近看起来做了不少神神叨叨的最短路。感觉这道题的解题思路非常的奇怪。不看正解还想不到……下面是题解的讲法:

当T<= 10000的时候,可以设 vis[i][j] 代表到达第i个点时间为j是否合法。 这样是O(T*m),应该可以拿到小数据,就没打了。
当T很大的时候,我们考虑如果0 -> x -> n - 1路径时间为T,且 从x出发有一个时间为d的环,则 一定存在一个K满足 K + p*d = T(至少T满足条件),这样我们就能绕着环走p次就能构成一条时间为T的路径。
显然要求的路径一定经过 0,而且在合法情况下从0号点出发一定存在一条边,否则0号点和n - 1号就是不联通的。随便取一条边时间为d, 则能构成从0号点出发的一个时间为2d的环。这样原题就化为最短路问题了,dis[i][j] 代表到达i号点,时间为 j + p * 2d,最小的 j+p*2d。最后判断dis[n -1][T % 2d] 是否小于等于T即可。实际上就是在30%的基础上缩减状态。时间复杂度为O(m*d)。

#include
#include
#include
#include
#include
#include
#define ll long long
#define MOD 1000002
using namespace std;
int C,n,m,zz,head[52],mod;
ll T,dis[52][20002];
struct bian{int to,nx,v;} e[202];
int q[10000002][2];
void insert(int x,int y,int z)
{
	zz++; e[zz].to=y; e[zz].v=z; e[zz].nx=head[x]; head[x]=zz;
	zz++; e[zz].to=x; e[zz].v=z; e[zz].nx=head[y]; head[y]=zz;
	if(x==0||y==0) mod=2*z;
}
void init()
{
	memset(head,0,sizeof(head));
	zz=0; mod=-1;
	scanf("%d%d%I64d",&n,&m,&T);
	int i,x,y,z;
	for(i=1;i<=m;i++)
	   {scanf("%d%d%d",&x,&y,&z);
	    insert(x,y,z);
	   }
}
void spfa()
{
	int i,t=0,w=1,x,p,y,d;
	memset(dis,127,sizeof(dis));
	q[0][0]=0; q[0][1]=0; dis[0][0]=0;
	while(t!=w)
	   {x=q[t][0]; y=q[t][1]; t=(t+1)%MOD;
	    //t++;
	    for(i=head[x];i;i=e[i].nx)
	       {p=e[i].to;
		    d=(e[i].v+y)%mod;
		    if(dis[p][d]>dis[x][y]+e[i].v)
		       {dis[p][d]=dis[x][y]+e[i].v;
			    q[w][0]=p; q[w][1]=d;
			    w=(w+1)%MOD;
			    //w++;
			   }
		   }
	   }
	if(dis[n-1][T%mod]<=T) puts("Possible");
	else puts("Impossible");
}
int main()
{
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout);
	scanf("%d",&C); 
	while(C--)
	   {init();
	    if(mod==-1) {puts("Impossible"); continue;}
	    spfa();
	   }
	return 0;
}

你可能感兴趣的:(图论)