题目来源:
https://www.luogu.org/problemnew/show/P4779
题目描述:
题目背景
狗哥做烂了最短路,突然机智的考了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
说明
好好看一看再写哟w
解题思路:
单源最短路的模板,不过这题数据是精心构造的,我以前很喜欢用spfa,在这题用的时候就崩了,后来想起来,在哪看过spfa的时间复杂度不稳定,最坏的情况是会到o(n^2),所以我赶紧改成了dijsktra+优先队列做了,这样就可以通过了,看来以后时间充裕还是用dij比较好。。
代码:
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<stack>
#include<vector>
#include<cstdio>
#define ll long long
#define inf 1e9+10
using namespace std;
const int maxn=1e5+10;
struct newt
{
int to,next,val;
}e[2*maxn];
int n,cnt,m,vis[maxn],head[maxn];
int dis[maxn];
priority_queue<pair<ll,int> >q;
void addedge(int u,int v,int w)
{
e[cnt].to=v;
e[cnt].val=w;
e[cnt].next=head[u];
head[u]=cnt++;
}
int main()
{
memset(head,-1,sizeof(head));
cnt=0;int S;
scanf("%d%d%d",&n,&m,&S);
for(int i=1;i<=n;i++)dis[i]=1e10+10;
for(int i=1;i<=m;i++)
{
int a,b, w;
scanf("%d%d%d",&a,&b,&w);
addedge(a,b,w);
}
q.push(make_pair(0,S));
dis[S]=0;
while(!q.empty())
{
int now=q.top().second;
q.pop();
if(vis[now])continue;
vis[now]=1;
for(int i=head[now];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(dis[v]>dis[now]+e[i].val)
{
dis[v]=dis[now]+e[i].val;
q.push(make_pair(-dis[v],v));
}
}
}
for(int i=1;i<=n;i++)
printf("%d ",dis[i]);
puts("");
return 0;
}