传送门
题意很明确:找到第二短路
考虑
D
i
j
k
s
t
r
a
和
S
p
f
a
Dijkstra和Spfa
Dijkstra和Spfa算法,维护两个标记
d
i
s
1
[
u
]
dis1[u]
dis1[u]和
d
i
s
2
[
u
]
dis2[u]
dis2[u],
d
i
s
1
[
u
]
dis1[u]
dis1[u]表示最短路
d
i
s
2
[
u
]
dis2[u]
dis2[u]表示第二短路
D i j k s t r a 算 法 Dijkstra算法 Dijkstra算法
#include<bits/stdc++.h>
#define rep(i,a,b) for(register int (i)=(a);(i)<=(b);(i)++)
#define don(i,a,b) for(register int (i)=(a);(i)>=(b);(i)--)
using namespace std;
const int maxn=1e6+10;
const int maxm=1e3+10;
int s,m,cnt=0;
int head[maxn],dis1[maxn],dis2[maxn],vis[maxm][maxm];
template <class t> inline void read(t &x) {
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
struct {
int v,w,nex;
}e[maxn<<1];
struct node{
int u,dis;
node(int _u = 0,int _dis = 0):u(_u),dis(_dis){}
friend bool operator < (const node &A,const node &B) {
return A.dis>B.dis;
}
};
void add(int u,int v,int w) {
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
void readdata() {
memset(head,-1,sizeof(head));
read(s),read(m);
rep(i,1,m) {
int x,y,z;
read(x),read(y),read(z);
add(x,y,z);add(y,x,z);
}
}
void dijkstra() {
priority_queue<node> q;
dis1[1]=0;
q.push(node(1,0));
while(q.size()) {
node A=q.top();
int u=A.u,dis=A.dis;
q.pop();
if(dis>dis2[u]) continue;//如果大于第二短路,直接跳过,不用考虑
if(vis[u][dis]) continue;
vis[u][dis]=true;
for(int i=head[u];~i;i=e[i].nex) {
int v=e[i].v,w=e[i].w;
int d=dis+w;//d可以相当于dis2[u]+w
if(d<dis1[v]){//如果第二短路比最短路还优,交换第一二短路
swap(dis1[v],d);
if(!vis[v][dis1[v]]);
q.push(node(v,dis1[v]));
}
if(d>dis1[v] && d<dis2[v]){//如果小于最短路,下面套Dijkstra的标准模板
dis2[v]=d;
if(!vis[v][dis2[v]]);
q.push(node(v,dis2[v]));
}
}
}
}
void work() {
memset(vis,false,sizeof(vis));
memset(dis1,0x3f,sizeof(dis1));
memset(dis2,0x3f,sizeof(dis2));
dijkstra();
printf("%d\n",dis2[s]);
}
int main() {
freopen("a.txt","r",stdin);
readdata();
work();
return 0;
}
S p f a 版 本 Spfa版本 Spfa版本
#include<bits/stdc++.h>
#include<queue>
#define rep(i,a,b) for(register int (i)=(a);(i)<=(b);(i)++)
#define don(i,a,b) for(register int (i)=(a);(i)>=(b);(i)--)
using namespace std;
const int maxn=1e6+10;
const int maxm=1e3+10;
int s,m,cnt=0;
int vis[maxn],head[maxn],dis[maxn][2];
template <class t> inline void read(t &x) {
x=0;int f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
x*=f;
}
struct node{
int v,w,nex;
}e[maxn<<1];
void add(int u,int v,int w) {
e[++cnt].v=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt;
}
void readdata() {
memset(dis,0x3f,sizeof(dis));
read(s);read(m);
rep(i,1,m) {
int x,y,z;
read(x),read(y),read(z);
add(x,y,z);add(y,x,z);
}
}
void spfa() {
queue<int> q;
dis[1][0]=0;
q.push(1);
while(q.size()) {
int u=q.front();
q.pop();
for(int i=head[u];i;i=e[i].nex) {
int v=e[i].v,w=e[i].w;
if(dis[v][0]>dis[u][0]+w) {//如果能够进行松弛制作
dis[v][1]=dis[v][0];//第二短路继承dis[v][0]
dis[v][0]=dis[u][0]+w;//更新最短路
q.push(v);
}
else if(dis[v][1]>dis[u][0]+w && dis[u][0]+w!=dis[v][0]) {
//如果最短路无法进行松弛操作且第二短路严格小于dis[u][0]+w,则可以松弛第二短路
dis[v][1]=dis[u][0]+w;
q.push(v);
}
else if(dis[v][1]>dis[u][1]+w) {
//最后一种情况是第二短路能够自己进行松弛操作
dis[v][1]=dis[u][1]+w;
q.push(v);
}
}
}
}
void work() {
memset(vis,false,sizeof(vis));
spfa();
printf("%d\n",dis[s][1]);
}
int main() {
//freopen("a.txt","r",stdin);
readdata();
work();
return 0;
}