洛谷 P2384 最短路 题解

题目链接

比较套路的一道题,本题的方法也可以用来做树的最大乘积独立集

由于本题需要取模,所以不能直接求最短路
我们考虑将每条边取对数,也就是将边权为 w w w 的边变为 log ⁡ 2 w \log_2w log2w
这样,根据幂的性质,我们就将乘积最短路转化为了普通最短路,证明显然
最后记得要把边权变回来输出

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const long long Maxn=1010,Maxm=1000000+10;
const long long inf=0x3f3f3f3f;
const long long mod=9987;
long long nxt[Maxm],to[Maxm];
long long val[Maxm],head[Maxn];
double len[Maxm],dis[Maxn];
long long dist[Maxn];
bool vis[Maxn];
long long n,m,edgecnt;
struct node{
    
    
	long long pos;
	double dis;
	node(long long x,double y)
	{
    
    
		pos=x,dis=y;
	}
	bool operator <(const node &x)const
	{
    
    
		return x.dis<dis;
	}
};
inline long long read()
{
    
    
	long long s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*w;
}
inline void add(long long x,long long y,double c,long long v)
{
    
    
	++edgecnt;
	nxt[edgecnt]=head[x];
	to[edgecnt]=y;
	len[edgecnt]=c;
	val[edgecnt]=v;
	head[x]=edgecnt;
}
void dij(long long s)
{
    
    
	priority_queue <node> q;
	fill(dis+1,dis+1+n,inf*1.0);
	dis[s]=0.0,dist[s]=1ll,vis[s]=1;
	q.push(node(s,0.0));
	while(q.size())
	{
    
    
		long long x=q.top().pos;
		q.pop();
		for(long long i=head[x];i;i=nxt[i])
		{
    
    
			long long y=to[i];
			if(dis[y]>dis[x]+len[i])
			{
    
    
				dis[y]=dis[x]+len[i];
				dist[y]=(dist[x]*val[i])%mod;
				if(!vis[y])vis[y]=1,q.push(node(y,dis[y]));
			}
		}
	}
}
int main()
{
    
    
	n=read(),m=read();
	for(long long i=1;i<=m;++i)
	{
    
    
		long long x=read(),y=read(),z=read();
		add(x,y,log2(z),z);
	}
	dij(1);
	printf("%lld\n",dist[n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Brian_Pan_/article/details/109246921
今日推荐