P2384洛谷 最短路

题目描述

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

输入输出格式

输入格式:

第一行读入两个整数n,m,表示共n个点m条边。 接下来m行,每行三个正整数x,y,z,表示点x到点y有一条边权为z的边。

输出格式:

输出仅包括一行,记为所求路径的边权之积,由于答案可能很大,因此狗哥仁慈地让你输出它模9987的余数即可。

输入样例:
3   3

1  2  3

2  3  3

1  3  10

输出:
9

分析:

将起点到终点的所有路径相乘并作为答案,根据Dijkstra的算法思想可以每次贪心贪到当前最短的边再相乘便可以得到答案

这道题只需要将dijkstra的模板修改一下即可作为刚开始学最短路练手还算不错的

如果有什么不明白的那么说明你对dijkstra这个算法不熟练,请移步到我的dijkstra模板博客

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <iomanip>
using namespace std;
typedef int insert;
#define in cin
const int INF=0x3f3f3f3f;
const int N=1000+100;
insert edges[N][N],dis[N],vis[N];
insert n,m,x,y,z;
long long sum=1;
void value()
{
    memset(edges,INF,sizeof(edges));
    memset(dis,INF,sizeof(dis));
    for(int i=1;i<=m;i++)
    {
        in>>x>>y>>z;
        edges[x][y]=z;
    }
    dis[1]=0;
    return;
}
void dijkstra()
{
    for(int k=1;k<=n;k++)
    {
        insert minn=INF,pos;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]&&dis[i]<minn)
            {
                pos=i;
                minn=dis[i];
                if(minn!=0)//因为这里dis[1]=0如果相乘答案绝对会出错所以必须排除dis[1]=0
                sum*=minn;//minn为每个松弛点的值所以每次将它们相乘即可
            }
        }
        vis[pos]=true;
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]&&dis[i]>edges[pos][i])//这个地方为修改的地方,因为这题没有必要将源点到每个节点的最短路径算出来,只需要将每个节点之间的最短路径计算出来即可
            dis[i]=edges[pos][i];
        }
    }
    return;
}
int main()
{
    in>>n>>m;
    value();
    dijkstra();
    cout<<sum%9987;
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/CCCPKeay/p/10291151.html