1. 程式人生 > >USACO2007NOV——次短路徑Roadblocks(次短路)

USACO2007NOV——次短路徑Roadblocks(次短路)

描述
貝西所在的牧場一共有 N 個地點。 M 條雙向通行的道路連線這些地點,其中第 i 條道路連線 Ai 和 Bi,長度為 Li。貝西想從第一個地點走到第 N 個地點,由於路上風景不錯,她決定不走最短 路徑,而選擇次短路徑。次短路徑的長度嚴格大於最短路徑。如果有兩條路徑的長度都是最短的,那 麼它們都不算次短路徑。次短路徑允許重複通過一些道路或地點。請你幫助貝西找出次短路徑的長度 吧,輸入資料保證次短路徑一定存在
輸入
第一行:兩個整數 N 和 M, 1 ≤ N ≤ 5000, 1 ≤ M ≤ 10^5 • 第二行到第 M + 1 行:第 i + 1 行有三個整數 Ai, Bi 和 Li, 1 ≤ Ai; Bi ≤ N; 1 ≤ Li ≤ 5000
輸出
單個整數:表示從第一個點到最後一個點的次短路徑長度
樣例輸入
4 4
1 2 100
2 4 200
2 3 250
3 4 100
樣例輸出
450
提示
最短路是 1 → 2 → 4,總長度為 300,次短路 是 1 → 2 → 3 → 4,總長度為 450

次短路的求法:

從起點和終點分別跑一次SPFA

然後列舉每一條邊,看能不能更新次小答案就是了

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char ch=getchar();
	int res=0;
	while(!isdigit(ch)) ch=getchar();
	while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res;
}
int n,m,k,cnt,l,ans,r,last,
adj[5005],nxt[200005],to[200005],val[200005],dis1[5005],dis2[5005]; bool vis[10005]; struct edge{ int u,v,w; }e[200005]; inline void addedge(int u,int v,int w){ nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w; nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,val[cnt]=w; } inline void spfa(int s,int *dis){ int q[500005],qn; memset(
vis,false,sizeof(vis)); last=1e9; q[qn=1]=s,vis[s]=true,dis[s]=0; for(int ql=1;ql<=qn;ql++){ int u=q[ql]; for(int e=adj[u];e;e=nxt[e]){ int v=to[e]; if(dis[u]+val[e]<dis[v]) { dis[v]=dis[u]+val[e]; if(!vis[v]){ vis[v]=true; q[++qn]=v; } } } vis[u]=false; } return; } int main(){ n=read(),m=read(); for(int i=1;i<=m;i++){ int u=read(),v=read(),w=read(); e[i].u=u,e[i].v=v,e[i].w=w; addedge(u,v,w); } memset(dis1,127/3,sizeof(dis1)); memset(dis2,127/3,sizeof(dis2)); spfa(1,dis1); spfa(n,dis2); int ans=1e9; for(int i=1;i<=m;i++){ int u=e[i].u,v=e[i].v; int tmp=dis1[u]+dis2[v]+e[i].w; if(tmp>dis1[n]&&tmp<ans){ ans=tmp; } tmp=dis1[v]+dis2[u]+e[i].w; if(tmp>dis1[n]&&tmp<ans){ ans=tmp; } } cout<<ans<<'\n'; }