洛谷P2865

感受此题可做为严格次短路的模板,所以来写一写ios

Description

给定 \(n\) 个点,\(r\) 条双向道路,求从 \(1\) 号点到 \(n\) 号点的严格次短路spa

Solution

维护两个变量,最短路和次短路code

\(Dis[i][0]\) 表示从 \(1\) 号点到 \(i\) 号点的最短路,\(Dis[i][1]\) 表示从 \(1\) 号点到 \(i\) 号点的次短路ip

而后考虑什么状况下会对最短路或次短路的更新形成影响get

\(fr\) 是当前节点,\(to\) 是当前节点连出去的某个节点string

\(Dis[to][0]>Dis[fr][0]+e[i].dis\) 时,代表当前点 \(to\) 的最短路再也不是最短的,就把当前最短路更新成次短路,而后再更新最短路it

\(Dis[to][1]>Dis[fr][1]+e[i].dis\) 时,发现当前点 \(to\) 的次短路能够更短,但对最短路无影响,就只更新次短路io

\(Dis[to][1]>Dis[fr][0]+e[i].dis\) 而且 \(Dis[to][0]<Dis[fr][0]+e[i].dis\) 时,代表当前点 \(to\) 的次短路能够更新,而最短路已是最优,则只更新次短路模板

综上,每次按上述方法更新每条边,就能够求出到每一个点的严格次短路class

最后答案就是 \(Dis[n][1]\)

Code

#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 5010
#define LL long long
#define uLL unsigned long long

using namespace std;

queue<int> q;
int n,r,tot,head[maxn];
int Dis[maxn][3],vis[maxn];
struct edge{int fr,to,dis,nxt;}e[maxn<<1];

inline int read(){
	int s=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
	return s*w;
}

inline void add(int fr,int to,int dis){
	e[++tot].fr=fr;e[tot].to=to;
	e[tot].dis=dis;e[tot].nxt=head[fr];
	head[fr]=tot;
}

inline void SPFA(){
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=head[u];i;i=e[i].nxt){
			int to=e[i].to,dis=e[i].dis; 
			if(Dis[to][0]>Dis[u][0]+dis){
				Dis[to][1]=Dis[to][0];
				Dis[to][0]=Dis[u][0]+dis;
				if(!vis[to]) vis[to]=1,q.push(to);
			}
			if(Dis[to][1]>Dis[u][1]+dis){
				Dis[to][1]=Dis[u][1]+dis;
				if(!vis[to]) vis[to]=1,q.push(to); 
			}
			if(Dis[to][1]>Dis[u][0]+dis&&Dis[to][0]<Dis[u][0]+dis){
				Dis[to][1]=Dis[u][0]+dis;
				if(!vis[to]) vis[to]=1,q.push(to);
			}
		}
	}
}

int main(){
	n=read();r=read();
	memset(Dis,63,sizeof Dis); 
	q.push(1);vis[1]=1;Dis[1][0]=0; 
	for(int i=1,fr,to,dis;i<=r;i++){
		fr=read();to=read();dis=read();
		add(fr,to,dis);add(to,fr,dis);
	}
	SPFA();printf("%d",Dis[n][1]);
	return 0;
}
相关文章
相关标签/搜索