1. 程式人生 > >洛谷 P4779 【模板】單源最短路徑(標準版) 題解

洛谷 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;
}