黄昏-dijkstra

小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]<<'
';
	return 0;
}
原文地址:https://www.cnblogs.com/wuwendongxi/p/14076081.html