P2384传送门
思路
这道题与板子题不同的是 问的是乘积最大 但是如果是乘积最大的话看数据按照常规思路肯定会爆的 但是需要取模的你就不能确定谁的乘积很大了 如果用对数来算的话是不是就可以将乘积与加法连接起来了 比如log a +log b==loga*b 如果路径乘积大于你的话 那么是不是我的对数和也是大于你的如果知道这就好了
而且还需要注意的东西是如果我们能找到最短路径的最小值 是不是根据路径回溯还可以找到路径的轨迹 找到轨迹的话你就可以把起点到终点的所有边全部乘起来取模了
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
const int maxn=1e5;
const int inf=0x3f3f3f3f;
vector<pii>edge[maxn];
int n,m;
double dis[maxn];
int pre[maxn];
priority_queue<pii,vector<pii>,greater<pii> > q;
void dijkstra(int x)
{
for(int i=1;i<=n;i++)
{
dis[i]=2147483647;
}
dis[x]=0;
q.push(pii(0,x));
while(!q.empty())
{
pii t=q.top();
q.pop();
int point=t.second;
int value=t.first;
if(value>dis[point])
{
continue;
}
for(int i=0;i<edge[point].size();i++)
{
int p=edge[point][i].first;
int w=edge[point][i].second;
if(dis[point]+log(w)<dis[p])
{
dis[p]=dis[point]+log(w);
pre[p]=point;
q.push(pii(dis[p],p));
}
}
}
}
int main()
{
int a,b,c;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
edge[a].push_back(pii(b,c));
edge[b].push_back(pii(a,c));
}
dijkstra(1);
int t=n;
int mul=1;
while(t!=1)
{
int ans;
for(int i=0;i<edge[t].size();i++)
{
if(edge[t][i].first==pre[t])
{
ans=edge[t][i].second;
break;
}
}
mul=(mul*ans)%9987;
t=pre[t];
}
printf("%d\n",mul);
return 0;
}