JZOJ 3890. 长途旅行【同余最短路】


题目:

传送门


题意:

给出一张图,我们要在恰好为 T T T的这个时间点到达 n n n号城市,每个城市可以被经过多次


分析:

爽快跑一遍同余最短路,至于 m n mn mn的选取,我们就取与 n n n号城市相连的权值最小的那条边
之后如果 d i s n , t % ( 2 ∗ m n ) ≤ t dis_{n,t\%(2*mn)} \leq t disn,t%(2mn)t就说明可以,否则就不行


代码:

#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define LL long long
using namespace std;
inline LL read() {
    
    
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){
    
    if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){
    
    d=d*10+s-'0';s=getchar();}
    return d*f;
}
struct node{
    
    
	LL to,next,w;
}e[205];
LL ls[55],cnt=0;
void add(LL x,LL y,LL w)
{
    
    
	e[cnt]=(node){
    
    y,ls[x],w};
	ls[x]=cnt++;
	return;
}
LL dis[55][20005];bool tf[55][20005];int mw;
void dij()
{
    
    
	memset(tf,0,sizeof(tf));
	memset(dis,0x3f3f3f3f,sizeof(dis));
	dis[1][0]=0; 
	priority_queue<pair<LL,pair<LL,LL> > > q;
	q.push(make_pair(0,make_pair(1,0)));
	while(q.size())
	{
    
    
		LL u=q.top().second.first,mou=q.top().second.second;
		q.pop();
		if(tf[u][mou]) continue;
		tf[u][mou]=1;
		for(LL i=ls[u];~i;i=e[i].next)
		{
    
    
			LL v=e[i].to,mov=(mou+e[i].w)%(mw*2);
			if(dis[u][mou]+e[i].w<dis[v][mov])
			{
    
    
				dis[v][mov]=dis[u][mou]+e[i].w;
				q.push(make_pair(-dis[v][mov],make_pair(v,mov)));
			}
		}
	}
	return;
}
int main()
{
    
    
	LL q=read();
	while(q--)
	{
    
    
		LL n=read(),m=read(),t=read();mw=2147483647;
		memset(ls,-1,sizeof(ls));cnt=0;
		for(LL i=1;i<=m;i++)
		{
    
    
			int x=read()+1,y=read()+1,w=read();
			add(x,y,w);add(y,x,w);
			if(x==n||y==n) mw=min(mw,w);
		}
		dij();
		if(dis[n][t%(mw*2)]<=t) printf("Possible\n");
		else printf("Impossible\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35786326/article/details/103015681
今日推荐