#同余最短路/bfs# [jzoj 3890] 【NOIP2014模拟10.25B组】长途旅行

题目

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”。(不含引号)。


解题思路

可以参考这道题目#同余最短路# [51nod] 遥远的旅途

#同余最短路/bfs# [jzoj 3890] 【NOIP2014模拟10.25B组】长途旅行_第1张图片

注意连边只需要连接与 n n n相连的最短边跑最短路
其实可以只跑bfs判断是否可行( d i j dij dij的时间复杂度要高)。
假如 t l e tle tle,与 1 1 1连边就好了,蜜汁 A C AC AC


代码

#include
#include
#include
#include
#include
#define mp(x,y,z) make_pair(x,make_pair(y,z))
#define ll long long
#define rr register 
using namespace std; 
const int N=110,M=20010; 
struct node{int y,z,next;}a[N*M];
int n,m,T,tot,head[N]; ll t,d[N][M]; 
bool flag,v[N][M]; 
inline int read(){
	int p=0; char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) p=(p<<3)+(p<<1)+c-48,c=getchar();  return p;
}
inline void add(int x,int y,int z){a[++tot]=(node){y,z,head[x]}; head[x]=tot;}
inline void dij(int qh){
	memset(d,0x3f,sizeof(d)),memset(v,0,sizeof(v)); 
	priority_queue<pair<ll,pair<int,int> > >q; 
	d[1][0]=0; q.push(mp(0,1,0)); 
	while(q.size()){
		int x=q.top().second.first,mx=q.top().second.second; q.pop();
		if (v[x][mx]) continue; else v[x][mx]=1; 
		for(rr int i=head[x];i;i=a[i].next){
			int y=a[i].y,my=(a[i].z+mx)%qh; 
			if (d[y][my]>d[x][mx]+a[i].z) d[y][my]=d[x][mx]+a[i].z,q.push(mp(-d[y][my],y,my)); 
		}
	}
}
int main(){
	T=read(); 
	while(T--){
		flag=tot=0,memset(head,0,sizeof(head)); ll cnt=1e18; 
		n=read(),m=read(),scanf("%lld",&t); 
		for(rr int i=1,x,y,z;i<=m;i++) x=read(),y=read(),z=read(),add(x+1,y+1,z),add(y+1,x+1,z); 
		for(rr int i=head[1];i;i=a[i].next) cnt=min(cnt,1ll*a[i].z*2); 
		dij(cnt); 
		if (d[n][t%cnt]<=t) flag=1;
		if (flag) printf("Possible\n"); else printf("Impossible\n"); 
	}
}

你可能感兴趣的:(最短路径,jzoj,3890,noip,长途旅行,同余最短路)