首先考虑暴力维护,显然极端数据就会炸裂,那么用什么来维护呢?
考虑一个很 NB 的公式log(n*m)=log(n)+log(m)
OK ,这道题到此结束
我们只要把乘积转化为对数,最后再还原就可以了,也不用考虑精度问题,本蒟蒻试着用pow,然后它死了。
代码
#include<bits/stdc++.h> using namespace std; const int mod=9987; const int N=1e3+5; const int M=1e6+5; int head[N],tot,n,m,pa[N][2]; double dis[N]; struct node{int to,nxt,val;}e[2*M]; inline void add(int u,int v,int w){e[++tot].to=v;e[tot].val=w;e[tot].nxt=head[u];head[u]=tot;} int read(){char ch=getchar();int fh=0; while(!isdigit(ch))ch=getchar(); while(isdigit(ch))fh=(fh<<1)+(fh<<3)+(ch^48),ch=getchar(); return fh; } void print(int u){ int ans=1;//逆推路径之积,顺便维护一下 while(pa[u][0]){ ans=(1ll*ans*pa[u][1])%mod;//乘上路径长 u=pa[u][0];//前驱节点继续查找 } cout<<ans<<endl;//输出答案 } bool b[N]; queue<int> q; void spfa(){//SPFA它活了 fill(dis+1,dis+n+1,1e9); q.push(1);b[1]=1;dis[1]=0;//放入初始起点 while(!q.empty()){ int u=q.front();q.pop();//队首出队 for(int i=head[u];i;i=e[i].nxt){//遍历每一条边 int v=e[i].to,w=e[i].val;//取出边 if(dis[v]>dis[u]+log2(w)){//如果可以更新 dis[v]=dis[u]+log2(w); pa[v][0]=u;pa[v][1]=w;//记录前驱路径 if(!b[v])q.push(v),b[v]=1;//如果没有放在队列内就可以更新 } } } print(n);//逆推 } int main(){ n=read();m=read();//读入 for(int i=1,u,v,w;i<=m;++i){ u=read();v=read();w=read(); add(u,v,w);add(v,u,w); } spfa(); }
原文地址:https://www.cnblogs.com/coder-cjh/p/11664361.html
时间: 2024-10-14 23:55:12