P2865 [USACO06NOV] Roadblocks G 题解

题意

这题给你一个无向图,让你求出次短路(比最短路长,比其他路短).

思维

这里要注意到题目是人类出的,也是给人类做的,更何况这只是一道蓝题,所以极大概率不是让你发明新算法.因此这里最有可能是最短路的变形题.我们发现次短路与最短路是有关系的,因为构成一个次短路只有两种可能:

1.固定一条边,求出起点和终点分别到端点的最短路径,这种路径可能是次短路.注意判定是否你直接找到最短路了.

2.最短路的一条边被重复走了.为什么不是多条边被重复走?因为这样就比只重复一条边的长了,不是次短路.

两种枚举即可.

算法

这里求最短路dijikstra SPFA都可以,作者用的是堆优化的dijikstra,因为某个算法已经死了,如果这是考场且没有负权边一定用dijikstra.

实现

dis数组开两个(或者开一个二维的),分别存从起点和终点跑的最短路,这样思路中的两种枚举方式都可以简单实现.要注意,第一种方法中枚举不要出现走重的情况,因为这种情况绝对不是次短路.

cpp 复制代码
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N=5e3+10, M=1e5+10;
ll n,m,dis[N][2],mi,ans=(1e12),sl=(1e12);
bool f[N];
struct node{
	ll u,d;
	bool operator < (const node &u) const{
		return u.d<d;
	}
};
vector<node>v[N];
void dij(int s, int x){
	priority_queue<node>q;
	for(int i=1;i<=n;i++) dis[i][x]=(1e12), f[i]=0;
	dis[s][x]=0, q.push({s,0});
	while(q.size()){
		node t=q.top();
		q.pop();
		if(f[t.u]) continue;
		else f[t.u]=1;
		for(int i=0;i<v[t.u].size();i++){
			int u=v[t.u][i].u, g=v[t.u][i].d;
			if(dis[u][x]>dis[t.u][x]+g){
				dis[u][x]=dis[t.u][x]+g, q.push({u,dis[u][x]});
			}
		}
	}
}
struct Edge{
	int u,v,w;
}t[M];
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>t[i].u>>t[i].v>>t[i].w;
		v[t[i].u].pb({t[i].v,t[i].w});
		v[t[i].v].pb({t[i].u,t[i].w});
	}
	dij(1,0), dij(n,1), mi=dis[n][0];
	for(int i=1;i<=m;i++){
		ll u=t[i].u, v=t[i].v, w=t[i].w;
		if(dis[u][0]+dis[v][1]>dis[u][1]+dis[v][0]) swap(u,v);
		ll s=dis[u][0]+dis[v][1]+w;
		if(s==mi) continue;
		ans=min(ans,s);
	}
	for(int i=1;i<=m;i++){
		ll u=t[i].u, v=t[i].v, w=t[i].w;
		if(dis[u][0]+dis[v][1]>dis[u][1]+dis[v][0]) swap(u,v);
		ll s=dis[u][0]+dis[v][1]+w;
		if(s!=mi) continue;
		sl=min(sl,w);		
	}ans=min(ans,mi+sl*2);
	cout<<ans;
	return 0;
}

这里两个swap可能匪夷所思,想象一根木棒两端固定在两个端点(起点和终点),很显然有两种摆法,一种摆法非常奇怪,绳子会长很多,因为这个摆法是从一条直线转了180度.这里就是如此.其他大家尽量理解.

相关推荐
历程里程碑8 分钟前
C++ 18智能指针:告别内存泄漏的利器
开发语言·c++
鲨莎分不晴28 分钟前
【前沿技术】Offline RL 全解:当强化学习失去“试错”的权利
人工智能·算法·机器学习
XFF不秃头1 小时前
力扣刷题笔记-全排列
c++·笔记·算法·leetcode
菜鸟233号1 小时前
力扣669 修剪二叉搜索树 java实现
java·数据结构·算法·leetcode
光羽隹衡2 小时前
机械学习逻辑回归——银行贷款案例
算法·机器学习·逻辑回归
Code Warrior2 小时前
【C++】智能指针的使用及其原理
开发语言·c++
能源系统预测和优化研究2 小时前
创新点解读:基于非线性二次分解的Ridge-RF-XGBoost时间序列预测(附代码实现)
人工智能·深度学习·算法
执笔论英雄2 小时前
【RL】ROLL下载模型流程
人工智能·算法·机器学习
yaoh.wang2 小时前
力扣(LeetCode) 100: 相同的树 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·跳槽
SadSunset2 小时前
力扣题目142. 环形链表 II的解法分享,附图解
算法·leetcode·链表