模擬賽 長途旅行(時間限制: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<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
#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;
}
發佈了367 篇原創文章 · 獲贊 2 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章