小T始终害怕黄昏。
黄昏就要来了。;
我们定义小T内心的恐惧是一-个n个点m条边的无向图,每一条边的边权将会给出,小T正在S号节点。
小T如果通过某种路径到达了T号节点,则小T克服了内心的恐惧。
我们定义路径长度为:这条路径上所有边的权值的乘积。
小T的内心起伏不定,已经记不清T点的具体位置了,所以小T想知道,如果他从S点开始出发,到达他当前所指
定的T号节点,所经过的路径长度最小是多少。
由于这个答案可能很大,你只需要输出答案对998244353取模的结果。
注意,S点到它本身的路径长度为1。也就是说,如果询问的T= S,你只需要输出1即可。
题解
- 将乘积转化为加法,2的幂次方,再跑最短路
- dis存2的幂次方,dispow存乘法实际值
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
const int mod=998244353;
const int inf=0x7fffffff;
const int maxn=100003;
int n,m,s;
long long dispow[maxn];
bool vis[maxn];
double dis[maxn];
struct fdfdfd{int to,val;double w;};
struct node{
int id; double w;
bool operator<(const node &x) const{return x.w<w;}
};
vector<fdfdfd> g[maxn];
priority_queue<node> q;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void dijkstra()
{
for(int i=1;i<=n;++i) dis[i]=inf; dis[s]=0; dispow[s]=1;
while(!q.empty()) q.pop();
q.push((node){s,0});
while(!q.empty())
{
int x=q.top().id; q.pop(); vis[x]=1;
for(int i=0;i<g[x].size();++i)
{
int v=g[x][i].to;
if(dis[x]+g[x][i].w<dis[v])
{
dis[v]=dis[x]+g[x][i].w;
dispow[v]=dispow[x]*g[x][i].val%mod;
if(!vis[v]) q.push((node){v,dis[v]});
}
}
}
}
int main()
{
//freopen("6289.in","r",stdin);
//freopen("6289.out","w",stdout);
n=read(); m=read(); s=read();
for(int i=1;i<=m;++i){
int u,v,w;double tw;u=read(); v=read(); w=read();
tw=log2(1.0*w);
g[u].push_back((fdfdfd){v,w,tw}); g[v].push_back((fdfdfd){u,w,tw});
}
dijkstra();
int T,x; T=read();
while(T--) x=read(),cout<<dispow[x]<<'\n';
return 0;
}