题意:给你无向带权图,求次短路径
题解:加一个次短路的数组,用于距记录源点到此点的次短路长度,注意初始化是源点到自己的次短路是极大值
接着再使用dijkstra算法,它是每次选用现在连上(记录了)的点与其他点的最小权值的边去更新其他所有的点
就是在dij的算法上进行简单的修改,需要修改的是每次最短路更新之后再更新次短路,但是保证更新的次短路大于记录的次短路并小于记录的最短路
#include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int inf=1<<29; const int maxn=200010; struct Edge { int v,val; Edge(int v,int val):v(v),val(val) {} bool operator < (const Edge &c)const//改写大顶堆成为小顶堆 { return val>c.val; } }; vector<Edge> vec[maxn]; int dis[maxn],secondis[maxn];//记录第二短路径 void init(int n) { for(int i=0; i<=n; ++i) { vec[i].clear(); } } void dijkstraSecond(int n,int s) { priority_queue<Edge> pque; for(int i=0; i<=n; ++i) { dis[i]=inf; secondis[i]=inf;//注意初始化 } //secondis[s]=0;//不能初始化 dis[s]=0; pque.push(Edge(s,0)); while(!pque.empty()) { Edge disE=pque.top(); pque.pop(); if(secondis[disE.v]<disE.val)//注意次短路都失败了才不能加上这条路 continue; for(int i=0; i<vec[disE.v].size(); ++i) { Edge endE=vec[disE.v][i]; int disnow=disE.val+endE.val;//注意这儿不能用dis求 if(dis[endE.v]>disnow)//松弛最短路 { swap(dis[endE.v],disnow);//由于松弛次短路,所以这儿是交换两者 pque.push(Edge(endE.v,dis[endE.v])); } if(secondis[endE.v]>disnow&&dis[endE.v]<disnow)//松弛次短路 { secondis[endE.v]=disnow; pque.push(Edge(endE.v,secondis[endE.v])); } } } } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { init(n); while(m--) { int u,v,c; scanf("%d %d %d",&u,&v,&c); vec[u].push_back(Edge(v,c)); vec[v].push_back(Edge(u,c)); } dijkstraSecond(n,1); // for(int i=1; i<=n; ++i) // { // printf("secondis[i]=%d\n",secondis[i]); // } printf("%d\n",secondis[n]); } return 0; }