题目描述
给定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; }