1. 程式人生 > >次短路

次短路

add inf p s st2 產生 int pre 節點 include

一、思想:

求次短路,可以通過求最短路得到次短路長度
1到n的次短路長度必然產生於:從1走到x的最短路 + edge[x][y] + y到n的最短路
首先預處理好1到每一個節點的最短路,和n到每一個節點的最短路
然後枚舉每一條邊作為中間邊(x,y)或者(y,x),如果加起來長度等於最短路長度則跳過,否則更新。
從1走到x的最短路 + edge[x][y] + y到n的最短路 給dist[n] 比較 找大於dist[n] 且是最小的那一個

二、代碼

#include <cstdio>
#include <cstring>
#include <queue>
#include 
<algorithm> using namespace std; const int R = 100000+5; const int INF = 0x3f3f3f3f; struct Node { int v; int w; int next; } edge[R*2]; int head[R]; int dist1[R],dist2[R];//距離數組,分別求1到所有點距離和n到所有點距離 bool vis[R]; int num; int n,m; void init() { num = 0; memset(head,-1,sizeof(head)); memset(dist1,
0x3f,sizeof(dist1)); memset(dist2,0x3f,sizeof(dist2)); } void add_edge(int u,int v,int w)//鄰接表 { edge[num].v = v; edge[num].w = w; edge[num].next = head[u]; head[u] = num++; } void SPFA(int u,int *dist)//u是給定點 dist是距離數組 { int i,v,w; queue<int> Q; memset(vis,false,sizeof
(vis)); dist[u] = 0; vis[u] = true; Q.push(u); while(!Q.empty()) { u = Q.front(); Q.pop(); vis[u] = false; for(i=head[u]; i!=-1; i=edge[i].next) { v = edge[i].v; w = edge[i].w; if(dist[v] > dist[u] + w) { dist[v] = dist[u] + w; if(!vis[v]) { vis[v] = true; Q.push(v); } } } } } int main() { while(scanf("%d%d",&n,&m)!=EOF)//n個點,m條邊 { int i,j,u,v,w;; init(); for(i=1; i<=m; i++) //無向圖,雙向間圖 { scanf("%d%d%d",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } SPFA(1,dist1);//求 1 到所有點的最短路 SPFA(n,dist2);//求 n 到所有點的最短路 int ans = INF; for(i=1; i<=n; i++) { for(j=head[i]; j!=-1; j=edge[j].next) { v = edge[j].v; w = edge[j].w; // 1 到 i這一點的最短路, n 到 j這一點的最短路 + edge[i][j] int tem = dist1[i] + dist2[v] + w; if(tem > dist1[n] && tem < ans) { ans = tem; } } } printf("%d\n",ans); } return 0; }

次短路