【刷题】【最短路】 luogu P2384 最短路

给定n个点的带权有向图,求从1到n的路径中边权之积最小的简单路径。

(来自题解)

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

由于log(n*m)=log(n)+log(m)

OK,这道题到此结束

我们只要把乘积转化为对数,最后再还原就可以了,因为精度要求,所以还是记录路径好些。

#include<cstdio>
#include<cstdlib>
#include<vector>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int n,m;
const int N=1003,inf=1<<30;
struct node
{
    int v;double w;
    node(int vv,double ww)
    { v=vv,w=ww; }
    node(){}
};
vector <node > g[N];
int sz[N],path[N][2];
double dis[N];

struct nd
{
    int v;double d;
    nd(int vv,double dd)
    { v=vv,d=dd; }
    nd(){}
    bool operator < (const nd & o) const
    { return d>o.d; }
};
priority_queue <nd> q;
void dijk()
{
    for(int i=2;i<=n;i++) dis[i]=inf;
    q.push(nd(1,0)); 
    
    while(!q.empty() )
    {
        int t=q.top() .v;double dd=q.top() .d;
        q.pop() ;
        if(dd!=dis[t]) continue;
        if(t==n) break;
        
        for(int i=0;i<sz[t];i++)
        {
            int nx=g[t][i].v ;
            if(dis[nx] > dis[t]+log(g[t][i].w ) )
            {
                dis[nx]=dis[t]+log(g[t][i].w );
                path[nx][0]=t,path[nx][1]=g[t][i].w ;
                q.push(nd(nx,dis[nx])); 
            }
        }
    }
    
}

int ans=1,mod=9987;
void get_path()
{
    int v=n;
    while(v!=1)
    {
        ans=(ans*path[v][1])%mod;
        v=path[v][0];
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    int u,v,w;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&w);
        g[u].push_back(node(v,w)); 
    }
    for(int i=1;i<=n;i++)
        sz[i]=g[i].size() ;
    
    dijk();
    get_path();
    printf("%d\n",ans);
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xwww666666/p/11670585.html
今日推荐