poj 1511 鄰接表+堆優化的dijstra
阿新 • • 發佈:2019-01-29
這題最終的意思很簡單,輸入圖,求出從源點到所有點的最短路,再把這個圖的所有邊反向,再求一次源點到所有點的最短路。
這個和poj另一道題很相似,合適這題 的意義在於資料。
你這個圖是無法用鄰接矩陣存下的,因為鄰接矩陣太大了,你只能用鄰接表。
那麼這個題就是用鄰接表的用優先佇列優化過的dijstra過的了。
(其實堆優化就是用優先佇列而已,不和那些人裝樣子……)
注意這個圖的所有邊反向是怎麼實現的。
AC程式碼:
程式碼有點長……不好意思水平有限……#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> using namespace std; const int maxe=1e6+10; const int maxv=1e6+10; const int inf=0x3f3f3f3f; typedef long long ll; int N,M; int restore[maxe][3]; int which=1; int head[maxv]; struct EDGE { int d,w,next; EDGE():next(-1){} }e[maxv]; void add(int s, int d,int w) { e[which].d=d; e[which].w=w; e[which].next=head[s]; head[s]=which++; } void initforgraph() { memset(head,-1,sizeof(head)); memset(e,0,sizeof(e)); } struct pnwdis { int pn,dist; friend bool operator<(pnwdis a,pnwdis b) { return a.dist>b.dist; } }; int dis[maxv]; void dijstra(int st) { bool settled[maxv]; priority_queue<pnwdis> Q; memset(settled,0,sizeof(settled)); while(!Q.empty()) Q.pop(); for(int i=1;i<=N;i++) dis[i]=inf; dis[st]=0; pnwdis stt; stt.pn=st; stt.dist=0; Q.push(stt); while(!Q.empty()) { pnwdis t=Q.top(); Q.pop(); if(settled[t.pn]) continue; settled[t.pn]=1; for(int i=head[t.pn];i!=-1;i=e[i].next) { int to=e[i].d; int mid=t.pn; if(!settled[to]) { if(dis[to]>dis[mid]+e[i].w) { dis[to]=dis[mid]+e[i].w; pnwdis tt; tt.pn=to; tt.dist=dis[to]; Q.push(tt); } } } } } void print() { for(int i=1;i<=N;i++) { printf("%d ",dis[i]); } printf("\n"); } int main() { int T; scanf("%d",&T); while(T--) { ll ans=0; scanf("%d%d",&N,&M); which=1; initforgraph(); int t1,t2,t3; for(int i=1;i<=M;i++) { scanf("%d%d%d",&t1,&t2,&t3); restore[i][0]=t1; restore[i][1]=t2; restore[i][2]=t3; add(t1,t2,t3); } dijstra(1); for(int i=1;i<=N;i++) ans+=dis[i]; initforgraph(); which=1; for(int i=1;i<=M;i++) { add(restore[i][1],restore[i][0],restore[i][2]); } dijstra(1); for(int i=1;i<=N;i++) ans+=dis[i]; cout<<ans<<endl; } }