P2865 Roadblocks(严格次短路)

https://www.luogu.com.cn/problem/P2865
https://loj.ac/problem/10076

(1)(n) 的严格次短路

考虑使用 dij
记录两个数组,dis[u],dis2[u] 分别表示 (1)(u) 的最短路,严格次短路
更新时,取出堆顶的节点 (u),设它在堆种的距离大小是 (now\_dis)(不是那两个数组里的值),遍历所以和它相邻的节点 (v)

  • (dis_v>now_dis+W_i),那就先 (dis2_v=dis_v),就是当前的最短路变成了严格次短路,然后再中 (v) 更新 (u),最后把 (dis_v,dis2_v) 都放入堆里
  • 对于其它情况,如果 (dis2_v>now_dis+W_i),且 (now_dis+W_i>dis_v),就只更新 (diw2_v) 并放入堆中,后一个条件是为了保证长度是严格次短

然后就不像一般的 dij 每个点只更新一次了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<iomanip>
#include<cstring>
#define reg register
#define EN std::puts("")
#define LL long long
inline int read(){
	register int x=0;register int y=1;
	register char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
	return y?x:-x;
}
#define N 5005
#define M 200005
struct graph{
	int fir[N],nex[M],to[M],w[M],tot;
	inline void add(int u,int v,int z){
		to[++tot]=v;w[tot]=z;
		nex[tot]=fir[u];fir[u]=tot;
	}
}G;
int n,m;
struct data{
	int i,dis;
}heap[N*20];
int size;
int dis[N],dis2[N];
inline void push(data x){
	heap[++size]=x;
	reg int i=size,fa;
	while(i>1){
		fa=i>>1;
		if(heap[fa].dis<=heap[i].dis) return;
		std::swap(heap[fa],heap[i]);i=fa;
	}
}
inline data pop(){
	data ret=heap[1];heap[1]=heap[size--];
	reg int i=1,ls,rs;
	while((i<<1)<=size){
		ls=i<<1;rs=ls|1;
		if(rs<=size&&heap[rs].dis<heap[ls].dis) ls=rs;
		if(heap[i].dis<=heap[ls].dis) break;
		std::swap(heap[ls],heap[i]);i=ls;
	}
	return ret;
}
inline void dij(){
	push((data){1,0});
	dis[1]=0;
	reg int u,v,nowdis;
	data tmp;
	while(size){
		tmp=pop();u=tmp.i;nowdis=tmp.dis;
		for(reg int i=G.fir[u];i;i=G.nex[i]){
			v=G.to[i];
			if(dis[v]>nowdis+G.w[i]){
				dis2[v]=dis[v];
				dis[v]=nowdis+G.w[i];
				push((data){v,dis[v]});
				push((data){v,dis2[v]});
			}
			else if(dis2[v]>nowdis+G.w[i]&&nowdis+G.w[i]>dis[v]){
				dis2[v]=nowdis+G.w[i];
				push((data){v,dis2[v]});
			}
		}
	}
}
int main(){
	n=read();m=read();
	for(reg int x,y,z,i=1;i<=m;i++){
		x=read();y=read();z=read();
		G.add(x,y,z);G.add(y,x,z);
	}
	std::memset(dis,0x3f,sizeof dis);std::memset(dis2,0x3f,sizeof dis2);
	dij();
	printf("%d",dis2[n]);
	return 0;
}
原文地址:https://www.cnblogs.com/suxxsfe/p/13371789.html