• 洛谷 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;
    }
  • 相关阅读:
    tuple 元组及字典dict
    day 49 css属性补充浮动 属性定位 抽屉作业
    day48 选择器(基本、层级 、属性) css属性
    day47 列表 表单 css初识
    day 46 http和html
    day 45索引
    day 44 练习题讲解 多表查询
    day 40 多表查询 子查询
    day39 表之间的关联关系、 补充 表操作总结 where 、group by、
    day38 数据类型 约束条件
  • 原文地址:https://www.cnblogs.com/nancheng58/p/10068208.html
Copyright © 2020-2023  润新知