长途旅行

来源:互联网 发布:开源云服务器软件 编辑:程序博客网 时间:2024/04/30 01:40

题目描述
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 , Case <= 5.
100%: 2 <= n <= 50, 1 <= m <= 100, 1 <= z <= 10000, 1 <= T <= 10^18, Case <= 15.

令dis[i,j]表示到i点花了j时间能否到达。但是t有10^18 这样状态明显爆炸,我们得想办法压缩状态。这题的精妙之处就在于我们选择一条边来回走,去了再回来,循环着走,一直耗着等时间到了我们在出发去中点。设这条边的长度为d,来回走的时间就为2d。dis[i][j] 代表到达i号点,时间为 j + p * 2d,最小的 j+p*2d,问题就转化成了最短路了。

varx,y,p,tot,i,n,m,z,t:longint;tl:int64;ret,len,next,head:array[0..200] of int64;dis:array[0..100,0..20002] of qword;ti,d:array[0..5000000] of longint;flag:array[0..100] of boolean;procedure ins(u,v,w:longint);begin  tot:=tot+1;  ret[tot]:=v;  len[tot]:=w;  next[tot]:=head[u];  head[u]:=tot;  if u=1 then p:=2*w;end;procedure spfa;vari,h,tail,u,v,j,tt:longint;begin  for i:=1 to n do    for j:=0 to p do      dis[i,j]:=1000000000000000009;  h:=0;  tail:=1;  d[1]:=1;  ti[1]:=0;  dis[1,0]:=0;  while h<>tail do  begin    h:=h+1;    u:=d[h];    tt:=ti[h];    i:=head[u];    while i<>0 do    begin      v:=ret[i];      if dis[n,tl mod p]<=tl then begin writeln('Possible'); exit; end;      if dis[v,(tt+len[i]) mod p]>dis[u,tt]+len[i] then      begin        dis[v,(tt+len[i]) mod p]:=dis[u,tt]+len[i];          tail:=tail+1;          d[tail]:=v;          ti[tail]:=(tt+len[i]) mod p;      end;      i:=next[i];    end;  end;  if dis[n,tl mod p]<=tl then begin writeln('Possible'); exit; end                         else begin writeln('Impossible'); exit; end;end;begin  readln(t);  while t>0 do  begin    t:=t-1;    fillchar(head,sizeof(head),0);    tot:=0;    readln(n,m,tl);    for i:=1 to m do    begin      readln(x,y,z);      x:=x+1;y:=y+1;      ins(x,y,z);      ins(y,x,z);    end;    spfa;  end;end.
0 0
原创粉丝点击