[USACO06NOV]路障Roadblocks
题目链接:路障
思路
- 次短路,顾名思义就是比当前最短路小的”最短路“,因此还是需要求出最短路
- 显而易见,次短路便是基于最短路的一种拓展
- 现在来分析一下次短路应具有的特点
- 小于最短路(以此得出当Dis[u]+E[i].dis==Dis[v]时,不能进行次短路更新,否则会导致次短路等于最短路)
- 大于其他路(因此,次短路只可能是从最短路Dis[u]或次短路Ans[u],到达v的)
- 如果有新最短路,则原最短路为新次短路
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; const int Max_N=5010,Max_M=1e5+7,inf=2147432637; typedef pair<int,int>node; struct Edge { int next,dis,to; } E[Max_M*2];//注意是无向图 int Head[Max_N],num_Edge,Dis[Max_N],vis[Max_N],Ans[Max_N]; int N,M; inline int Read(void)//快读 { int w=0,x=0; char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=x*10+(ch^48),ch=getchar(); return w?-x:x; } inline void Add_Edge(int from,int to,int dis)//建边 { E[++num_Edge].dis=dis; E[num_Edge].next =Head[from]; E[num_Edge].to =to; Head[from]=num_Edge; } inline void Dijkstra() { queue<int>Q; for(int i=1; i<=N; ++i) Dis[i]=inf,Ans[i]=inf;//初始化,注意也要对次短路进行初始化 Dis[1]=0; Q.push(1) ; while(!Q.empty()) { int u=Q.front(); Q.pop() ; vis[u]=0; for(int i=Head[u]; i; i=E[i].next ) { int v=E[i].to; if(Dis[v]>Dis[u]+E[i].dis )//如果找到新的最短路 { Ans[v]=Dis[v];//更新次小最短路 Dis[v]=Dis[u]+E[i].dis ; if(!vis[v]) { vis[v]=1; Q.push(v) ; } } else if(Ans[v]>Dis[u]+E[i].dis&&Dis[u]+E[i].dis!=Dis[v])//如果当前路径比最短路大,且小于次短路,则更新次短路 { Ans[v]=Dis[u]+E[i].dis ;//如果当前路径比次小最短路短,则更新次小最短路 if(!vis[v]) { vis[v]=1; Q.push(v) ; } } if(Ans[v]>Ans[u]+E[i].dis)//如果当前路径比次小最短路短,则更新次小最短路 { Ans[v]=Ans[u]+E[i].dis ;//如果当前路径比次小最短路短,则更新次小最短路 if(!vis[v]) { vis[v]=1; Q.push(v) ; } } } } } int main(void) { N=Read(),M=Read(); for(int i=1; i<=M; ++i) { int u=Read(),v=Read(),d=Read(); Add_Edge(u,v,d); Add_Edge(v,u,d); } Dijkstra(); printf("%d",Ans[N]); return 0; }