題目node
Dijkstra + 鏈式前向星 + 堆優化的題解。c++
這一題明顯是求最短路。與模板不一樣,它要求的是多源最短路,是每一個節點到源點的距離。函數
這裏若是用暴力,或者每一個節點求一遍,顯然在時間上是過不去的。(每一個節點求一遍的堆優化的Dijkstra是50分)優化
因此,就要用一個重要的結論:逆圖中源點到各個點的最短路就是原圖中各個點到源點的最短路。code
理解過程:隊列
咱們能夠想象一下,在原圖中,n --> 1的最短路,若是在反向圖中不就是 n <-- 1 嗎?get
有了這個結論,這道題就簡單多了:先求一個原圖的最短路,再求一個逆圖的最短路。這題就結束了。it
附上代碼:io
#include <bits/stdc++.h> #define MAXN 100005 #define INF 0x3f3f3f3f struct EDGE //鏈式前向星 { int to,nxt,val; } e[MAXN],ne[MAXN]; //原圖與逆圖 struct node //寫一個堆的結構體 { int d,pos; bool operator <( const node &x ) const {return x.d<d;} }; int cnt=0,adj[MAXN],nadj[MAXN]; int dis[MAXN]; bool vis[MAXN]; int ori=1,n,m; int ans=0; std::priority_queue < node > q; //優先隊列的堆優化 void addedge(int u,int v,int w) //存圖 { ++cnt; e[cnt].to=v; e[cnt].val=w; e[cnt].nxt=adj[u]; adj[u]=cnt; ne[cnt].to=u; ne[cnt].val=w; ne[cnt].nxt=nadj[v]; nadj[v]=cnt; } void init() //初始化 { for(int i=1;i<=n;++i) dis[i]=INF; std::memset(vis,0,sizeof(vis)); while(!q.empty()) q.pop(); } void Dijkstra(EDGE e[],int adj[]) //函數變量中記得帶上鄰接域 { init(); //千萬記得初始化 dis[ori]=0; q.push( (node) {0,ori}); while(!q.empty()) { node temp=q.top(); q.pop(); int u=temp.pos; if(vis[u]) continue; vis[u]=1; for(int i=adj[u];i;i=e[i].nxt) { int v=e[i].to; if(dis[v]>dis[u]+e[i].val) { dis[v]=dis[u]+e[i].val; if(!vis[v]) q.push( (node) {dis[v],v}); } } } } int main() { std::scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { int u,v,w; std::scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); } Dijkstra(e,adj); for(int i=1;i<=n;++i) ans+=dis[i]; Dijkstra(ne,nadj); for(int i=1;i<=n;++i) ans+=dis[i]; std::printf("%d",ans); return 0; }