[关闭]
@ysner 2018-06-06T21:52:44.000000Z 字数 2345 阅读 2068

长途旅行

图论 最短路


题面

给出一无向图,询问从号点出发,能否在恰好走的距离为时,到达号点。(可重复经过点和边)

解析

标记该状态是否走过,记搜。

注意到我们似乎很明确他重复走的路线。
于是一下,把变小。

  1. il void Pre()
  2. {
  3. mod=10000;
  4. Predfs(1,0,0);//找一条从起点到终点的路线,ysn表路线长度
  5. re ll yl=(t-mod)/ysn;
  6. yl-=yl%2;//保证这条路多走了偶数遍
  7. t-=yl*ysn;
  8. return;
  9. }

接下来记搜即可。

能搞成这么大,直接标空间时间一起炸飞。
但是,每个点有个状态,这个状态都是有价值的吗?
如果到点的路径上有一只大小为的环,那么假设,则)
那每个点设个状态不就成了,装作距离不存在的样子。
但我们实际上还是要统计距离来和比较,这点应存在数组中。
于是转型为,记录到该点的实际距离,且该数组满足性质。。
但距离再长些也不过是多走几圈环,我们还是记最短距离吧。
于是,我们期望着,不不不,是的值应当小于等于(小于,我们再走几圈环就可以了)。

于是这个环在哪?
根据以上分析,从点必须能到达这个环,除此以外具有任意性。
那就找连接的一条边吧。
为了使状态量最少,这条边应取最短边。

(为了卡常数,我交换了dp数组的两维

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cstdlib>
  6. #include<algorithm>
  7. #include<queue>
  8. #define ll long long
  9. #define re register
  10. #define il inline
  11. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  12. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  13. using namespace std;
  14. const int N=500,mod=10000;
  15. int T,n,m,cnt,h[N],f=0,ysn,d;
  16. ll t,dp[20005][105];
  17. bool vis[20005][105];
  18. struct Edge{int to,nxt,w;}e[N<<1];
  19. il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}
  20. il ll gi()
  21. {
  22. re ll x=0,t=1;
  23. re char ch=getchar();
  24. while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  25. if(ch=='-') t=-1,ch=getchar();
  26. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  27. return x*t;
  28. }
  29. il void wri(re int x)
  30. {
  31. if(x<0) putchar('-'),x=-x;
  32. if(x>9) wri(x/10);
  33. putchar(x%10+'0');
  34. }
  35. struct node{int u,len,w;bool operator < (const node &o) const {return w>o.w;}};
  36. priority_queue<node>Q;
  37. il void SPFA()
  38. {
  39. memset(dp,63,sizeof(dp));memset(vis,0,sizeof(vis));
  40. Q.push((node){1,0,0});dp[0][1]=0;
  41. while(!Q.empty())
  42. {
  43. re node now=Q.top();Q.pop();re int u=now.u,len=now.len%d,w=now.w;
  44. for(re int i=h[u];i+1;i=e[i].nxt)
  45. {
  46. re int v=e[i].to,lenn=(len+e[i].w)%d;
  47. if(dp[lenn][v]>dp[len][u]+e[i].w)
  48. {
  49. dp[lenn][v]=dp[len][u]+e[i].w;
  50. if(!vis[lenn][v]) vis[lenn][v]=1,Q.push((node){v,lenn,dp[lenn][v]});
  51. }
  52. }
  53. vis[len][u]=0;
  54. }
  55. }
  56. int main()
  57. {
  58. freopen("travel.in","r",stdin);
  59. freopen("travel.out","w",stdout);
  60. T=gi();
  61. while(T--)
  62. {
  63. n=gi();m=gi();t=gi();
  64. memset(h,-1,sizeof(h));cnt=0;
  65. fp(i,1,m)
  66. {
  67. re int u=gi()+1,v=gi()+1,w=gi();
  68. add(u,v,w);add(v,u,w);
  69. }
  70. d=1e9;
  71. for(re int i=h[1];i+1;i=e[i].nxt)
  72. {
  73. re int v=e[i].to;
  74. if(v^1) d=min(d,e[i].w);
  75. }
  76. d<<=1;
  77. SPFA();
  78. puts(dp[t%d][n]<=t?"Possible":"Impossible");
  79. }
  80. fclose(stdin);
  81. fclose(stdout);
  82. return 0;
  83. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注