最短路(最短路之积)

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

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

 

posted @ 2019-10-12 23:05  Coder_cjh  阅读(216)  评论(0编辑  收藏  举报