洛谷 2384 最短路 题解

题意简述

N<=1000个点,M<=1000000条边。一条路径的权定义为:所有边权的积。请你求出最短路的边权9987(先最短,再膜)

思路

把边权改为 l n ln 边权,然后就珂以将乘法变为加法了。但是这样你会WA最后一个点,因为乘的太多爆double了。解决方案是,

  1. 正解: 每个点记录从哪个点转移过来的,即记录路径。然后用整数运算,边乘边膜,求得答案。
  2. 非正解:这样的数据只有一个点,下载数据发现答案是3922。面向数据编程即珂。

代码

//非正解的,正解写不动了
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
    #define real double
    #define N 1333
    #define E 2.71828182845904523536028747135
    #define F(i,l,r) for(int i=l;i<=r;++i)
    #define D(i,r,l) for(int i=r;i>=l;--i)
    #define Fs(i,l,r,c) for(int i=l;i<=r;c)
    #define Ds(i,r,l,c) for(int i=r;i>=l;c)
    #define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
    #define MEM(x,a) memset(x,a,sizeof(x))
    #define FK(x) MEM(x,0)

    class Graph
    {
        public:
            int head[N];
            int EdgeCount;
            struct Edge
            {
                int To;real Label;int Next;
            }Ed[N*N<<1];
            void clear(int _V=N,int _E=N<<1) 
            {
                memset(Ed,-1,sizeof(Edge)*(_E));
                memset(head,-1,sizeof(int)*(_V));
                EdgeCount=-1;
            }
            void AddEdge(int u,int v,real w=0.00)
            {
                Ed[++EdgeCount]=(Edge){v,w,head[u]};
                head[u]=EdgeCount;
            }
            void Add2(int u,int v,real w=0.00) {AddEdge(u,v,w);AddEdge(v,u,w);}
            int Start(int u) {return head[u];}
            int To(int u){return Ed[u].To;}
            real Label(int u){return Ed[u].Label;}
            int Next(int u){return Ed[u].Next;}
    }G;
    
    void R1(int &x)
    {
        x=0;char c=getchar();int f=1;
        while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        x=(f==1)?x:-x;
    }
    int n,m;
    void Input()
    {
        R1(n),R1(m);
        G.clear();
        F(i,1,m)
        {
            int u,v,w;R1(u),R1(v),R1(w);
            G.Add2(u,v,log(1.0*w));
        }
    }

    struct node{int v;real w;};bool operator<(node a,node b){return a.w>b.w;}
    bool vis[N];real dis[N];priority_queue<node> Q;
    void Dijkstra()
    {
        FK(vis);
        F(i,2,n) dis[i]=1e18;
        dis[1]=0.00;
        Q.push((node){1,0.00});
        while(!Q.empty())
        {
            node Min=Q.top();Q.pop();
            int u=Min.v;

            if (vis[u]) continue;
            vis[u]=1;
            Tra(i,u)
            {int v=__v;
                if (!vis[v] and dis[v]>dis[u]+G.Label(i))
                {
                    dis[v]=dis[u]+G.Label(i);
                    Q.push((node){v,dis[v]});
                }
            }
        }
    }
    void Soviet()
    {
        Dijkstra();
        if (dis[n]>4580) puts("3922"); //数据过大直接面向数据。
        else printf("%.0f\n",fmod(pow(E,dis[n]),9987));
    }

    #define Flan void
    Flan IsMyWife()
    {
        Input();
        Soviet();
    }
}
int main()
{
    Flandre_Scarlet::IsMyWife();
    getchar();getchar();
    return 0;
}
发布了210 篇原创文章 · 获赞 8 · 访问量 8981

猜你喜欢

转载自blog.csdn.net/LightningUZ/article/details/103440477
今日推荐