1. 程式人生 > >51nod 1443 路徑和樹(單元最短路徑)

51nod 1443 路徑和樹(單元最短路徑)

std algo 技術分享 mage 它的 ont cst 3-9 while

技術分享

分析:很容易想到先搞一遍單源最短路徑,然後只保留最短路徑上的邊,接下來容易想到最小生成樹,但是因為有的邊只刪了一個方向,所以變成了有向圖了,要求的就是最小樹形圖,比較麻煩而且容易T。。。

實際上,考慮在連好的圖裏加一個點,肯定是加連向它的最短邊,類似貪心的思路,所以結果就是刪完後的圖中,每個點的最小前驅邊權的和。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 #include<vector>
 6 #include<algorithm>
 7
using namespace std; 8 typedef long long ll; 9 const int maxn=3e5+5; 10 const ll inf=1e18; 11 struct Edge{ 12 int u,v; 13 ll w; 14 Edge(int _u,int _v,ll _w):u(_u),v(_v),w(_w){} 15 }; 16 bool Cmp(Edge a,Edge b){ 17 return a.w<b.w; 18 } 19 vector<Edge> edges; 20 vector<int
>G[maxn]; 21 void AddEdge(int u,int v,ll w){ 22 edges.push_back(Edge(u,v,w)); 23 edges.push_back(Edge(v,u,w)); 24 G[u].push_back(edges.size()-2); 25 G[v].push_back(edges.size()-1); 26 } 27 28 int u,n,m; 29 ll dis[maxn]; 30 ll pre[maxn]; 31 bool inq[maxn]; 32 void spfa(){ 33 memset(inq,0
,sizeof(inq)); 34 memset(pre,0,sizeof(pre)); 35 for(int i=1;i<=n;i++)dis[i]=inf; 36 queue<int> Q; 37 Q.push(u); 38 inq[u]=true; 39 dis[u]=0; 40 while(!Q.empty()){ 41 int x=Q.front();Q.pop(); 42 inq[x]=false; 43 for(int i=0;i<G[x].size();i++){ 44 Edge &e=edges[G[x][i]]; 45 if(dis[e.v]>dis[e.u]+e.w){ 46 dis[e.v]=dis[e.u]+e.w; 47 pre[e.v]=e.w; 48 if(!inq[e.v]){inq[e.v]=true;Q.push(e.v);} 49 } 50 else if(dis[e.v]==dis[e.u]+e.w)pre[e.v]=min(pre[e.v],e.w); 51 } 52 } 53 } 54 int main(){ 55 // freopen("e:\\in.txt","r",stdin); 56 int from,to; 57 ll weight; 58 scanf("%d%d",&n,&m); 59 for(int i=0;i<m;i++){ 60 scanf("%d%d%lld",&from,&to,&weight); 61 AddEdge(from,to,weight); 62 } 63 scanf("%d",&u); 64 spfa(); 65 ll ans=0; 66 for(int i=1;i<=n;i++){ 67 ans+=pre[i]; 68 } 69 printf("%lld\n",ans); 70 return 0; 71 }

51nod 1443 路徑和樹(單元最短路徑)