Description
Bessie 來到一個小農場,有時她想回老家看看她的一位好友。她不想太早地回到老家,因爲她喜歡途中的美麗風景。她決定選擇次短路徑,而不是最短路徑。
農村有 R (1 <= R <= 100,000) 條雙向的路,每條路連接 N (1 <= N <= 5000) 個結點中的兩個。結點的編號是 1…N。Bessie 從結點 1出發,她的朋友(目的地)在結點 N。
次短路徑可以使用最短路徑上的路,而且允許退回,即到達一個結點超過一次。次短路徑是一種長度大於最短路徑的路徑(如果存在兩條或多條最短路徑存在,次短路徑就是比它們長,且不比其他任何的路徑長的路徑)。
Input
Line 1: 兩個用空格分隔的整數 N 和 R
Lines 2…R+1: 每行包含三個用空格分隔的整數: A, B, 和 D表示有一條路連接結點A和B,長度爲D (1 <= D <= 5000)。
Output
Line 1: 結點 1 到結點 N的次短路徑長度。
Sample Input
4 4
1 2 100
2 4 200
2 3 250
3 4 100
Sample Output
450
Data Constraint
Hint
【樣例說明】
兩條路徑: 1 -> 2 -> 4 (長度 100+200=300) 以及 1 -> 2 -> 3 -> 4(長度 100+250+100=450)
//written by zzy
題目大意:
求一個圖的次短路
題解:
跑兩邊spfa,處理出 號點 和 號點到所有點的單源最短路
再枚舉每條邊 ,用 到 到 到 的長度更新答案
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define N 5005
#define M 100005
#define Max 1000000007
using namespace std;
int i,j,n,m,p,a,b,c,ans;
int d1[N],dn[N];
bool vis[N];
int next[2*M],list[N],u[2*M],v[2*M],z[2*M];
queue<int> q;
void add(int x) {
next[++p]=list[x];
list[x]=p;
}
void spfa1() {
for (i=1;i<=n;i++) d1[i]=Max;
d1[1]=0;
q.push(1);
while (q.size()!=0) {
int x=q.front();
for (int t=list[x],to=v[t];t;t=next[t],to=v[t]) {
if (d1[x]+z[t]<d1[to]) {
d1[to]=d1[x]+z[t];
if (!vis[to])
vis[to]=true,q.push(to);
}
}
vis[x]=false,q.pop();
}
}
void spfa_n() {
for (i=1;i<=n;i++) dn[i]=Max;
dn[n]=0;
q.push(n);
while (q.size()!=0) {
int x=q.front();
for (int t=list[x],to=v[t];t;t=next[t],to=v[t]) {
if (dn[x]+z[t]<dn[to]) {
dn[to]=dn[x]+z[t];
if (!vis[to])
vis[to]=true,q.push(to);
}
}
vis[x]=false,q.pop();
}
}
int main()
{
scanf("%d%d",&n,&m);
for (i=1;i<=m;i++) {
scanf("%d%d%d",&a,&b,&c);
add(a); u[i*2-1]=a,v[i*2-1]=b,z[i*2-1]=c;
add(b); u[i*2]=b,v[i*2]=a,z[i*2]=c;
}
spfa1();
spfa_n();
ans=Max;
for (i=1;i<=2*m;i++)
if (d1[u[i]]+z[i]+dn[v[i]]>d1[n])
ans=min(ans,d1[u[i]]+z[i]+dn[v[i]]);
printf("%d",ans);
}