1. 程式人生 > >51Nod 1443 路徑和樹 —— dijkstra

51Nod 1443 路徑和樹 —— dijkstra

cst == 註意 lan using get prior 代碼 col

題目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1443

首先要得到一個最短路樹;

註意邊權和最小,因為在最短路中,每個點的 dis 都是固定的,所以邊權和最小...

邊權和會不同是因為,雖然 dis 固定,但由於組成一棵樹,所以有些邊被很多點算入 dis ,而它的邊權只應被算一次;

發現每個點對直接連向它的那條邊的選擇是相互獨立的,所以直接在那些邊中選最小的即可。

代碼如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include
<algorithm> #include<queue> using namespace std; typedef long long ll; int const xn=3e5+5; int n,m,hd[xn],ct,to[xn<<1],nxt[xn<<1],st; ll dis[xn],ans,w[xn<<1],fa[xn]; bool vis[xn]; struct N{ ll dis; int id; bool operator < (const N &y) const {return
dis>y.dis;} }; priority_queue<N>q; void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; w[ct]=z; hd[x]=ct;} int rd() { int ret=0,f=1; char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=0; ch=getchar();} while(ch>=0&&ch<=9)ret=(ret<<3)+(ret<<1
)+ch-0,ch=getchar(); return ret*f; } void dijkstra() { memset(dis,0x3f,sizeof dis); dis[st]=0; q.push((N){0,st}); while(q.size()) { int x=q.top().id; q.pop(); if(vis[x])continue; vis[x]=1; for(int i=hd[x],u;i;i=nxt[i]) { if(vis[u=to[i]])continue; if(dis[u]>dis[x]+w[i]) { dis[u]=dis[x]+w[i]; fa[u]=w[i]; q.push((N){dis[u],u}); } else if(dis[u]==dis[x]+w[i])fa[u]=min(fa[u],w[i]); } } } int main() { n=rd(); m=rd(); for(int i=1,x,y,z;i<=m;i++) { x=rd(); y=rd(); z=rd(); add(x,y,z); add(y,x,z); } st=rd(); dijkstra(); for(int i=1;i<=n;i++)ans+=fa[i]; printf("%lld\n",ans); return 0; }

51Nod 1443 路徑和樹 —— dijkstra