码迷,mamicode.com
首页 > 其他好文 > 详细

最短路(最短路之积)

时间:2019-10-13 00:30:55      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:sdi   pac   math   nod   mat   node   display   spl   char   

首先考虑暴力维护,显然极端数据就会炸裂,那么用什么来维护呢?

考虑一个很 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();
}

 

最短路(最短路之积)

标签:sdi   pac   math   nod   mat   node   display   spl   char   

原文地址:https://www.cnblogs.com/coder-cjh/p/11664361.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!