洛谷 P4779 【模板】單源最短路徑(標準版) 題解
阿新 • • 發佈:2019-01-26
題目來源:
題目描述:
題目背景
狗哥做爛了最短路,突然機智的考了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; }