洛谷 P2384 最短路

P2384 最短路
题目提供者Bosh
标签 图论 最短路 难度 普及/提高-
狗哥做烂了最短路,突然机智的考了Bosh一道,没想到把Bosh考住了…你能帮Bosh解决吗?
他会给你100000000000000000000000000000000000%10金币w
题目描述
给定n个点的带权有向图,求从1到n的路径中边权之积最小的简单路径。
输入输出格式
输入格式: 第一行读入两个整数n,m,表示共n个点m条边。 接下来m行,每行三个正整数x,y,z,表示点x到点y有一条边权为z的边。
输出格式: 输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此狗哥仁慈地让你输出它模9987的余数即可。
废话当然是一个数了w
//谢fyszzhouzj指正w
对于20%的数据,n<=10。
对于100%的数据,n<=1000,m<=1000000。边权不超过10000。
输入输出样例
输入样例#1: 3 3 1 2 3 2 3 3 1 3 10
输出样例#1: 9
说明

/*
直接spfa暴力.
数据很水.
如果边权值大一点就不能这样搞了.
*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define mod 9987
#define MAXM 1000001
#define MAXN 1001
using namespace std;
int n,m,g[MAXN][MAXN],head[MAXN],cut,pre[MAXN],ans=1;
bool b[MAXN];
long long dis[MAXN];
struct data{int v,next,z;double x;}e[MAXM];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
    return x*f;
}
void add(int u,int v,int z)
{
    e[++cut].v=v;
    e[cut].x=log(z);
    e[cut].z=z;
    e[cut].next=head[u];
    head[u]=cut;
}
void spfa()
{
    memset(dis,127,sizeof dis);
    queue<int>q;q.push(1);dis[1]=1;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v]>dis[u]*e[i].z)
            {
                dis[v]=dis[u]*e[i].z;
                pre[v]=u;
                if(!b[v]) b[v]=true,q.push(v);
            }
        }
    }
}
int main()
{
    int x,y,z;
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();g[x][y]=z;
        add(x,y,z);
    }
    spfa();
    printf("%d",dis[n]%mod);
    return 0;
}
/*
单源询问两点之间最小积路.
比较好的一种做法.
然后用log性质.
log(n*m)=log(n)+log(m)
然后我想最后取2的dis[n]次方作为ans.
但是因为double的缘故这个ans是错误的.
so我们在保证正确性的情况下记录路径求ans. 
*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#define mod 9987
#define MAXM 1000001
#define MAXN 1001
using namespace std;
int n,m,g[MAXN][MAXN],head[MAXN],cut,pre[MAXN],ans=1;
bool b[MAXN];
double dis[MAXN];
struct data{int v,next,z;double x;}e[MAXM];
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
    return x*f;
}
void add(int u,int v,int z)
{
    e[++cut].v=v;
    e[cut].x=log(z);
    e[cut].z=z;
    e[cut].next=head[u];
    head[u]=cut;
}
void spfa()
{
    memset(dis,127,sizeof dis);
    queue<int>q;q.push(1);dis[1]=0;
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].x)
            {
                dis[v]=dis[u]+e[i].x;
                pre[v]=u;
                if(!b[v]) b[v]=true,q.push(v);
            }
        }
    }
}
int main()
{
    int x,y,z;
    n=read(),m=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();g[x][y]=z;
        add(x,y,z);
    }
    spfa();
    x=n;
    while(pre[x])
    {
        ans=(ans*g[pre[x]][x]%mod)%mod;
        x=pre[x];
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/nancheng58/p/10068208.html