• 最短路(最短路之积)


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

    考虑一个很 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();
    }
  • 相关阅读:
    鱼眼拼接实验
    多字节字符集 unicode字符集
    GPU编程接口
    零基础学java第一天
    最牛的减肥方法
    近期思考
    c++的stl容器
    蓝桥杯历年穷举题
    git简单指令3
    git简单指令2
  • 原文地址:https://www.cnblogs.com/coder-cjh/p/11664361.html
Copyright © 2020-2023  润新知