首页 > 其他分享 >做题笔记:次短路(P2865)

做题笔记:次短路(P2865)

时间:2023-02-02 10:56:03浏览次数:40  
标签:int 短路 first 笔记 second P2865 now id dis

虽然算法难度达不到记笔记的级别但由于个人认为较为重要,故作记录。

抓住最短路和次短路的一个区别,最少一条边不同。

所以不妨正反( \(1\) 和 \(n\) )分别跑最短路。

然后枚举最短路除外的每条边。

此时 \(ans=\min (ans , firstdis[from]+w[edge]+seconddis[to])\) 。

其中 \(firstdis\) 为第一次 dij(1->n) 的 \(dis\) 数组。

\(seconddis\) 为第二次 dij(n->i) 的 \(dis\) 数组。

\(edge\) 表示遍历到的边,\(w[edge]\) 表示边权。

//writer:Oier_szc

#include <bits/stdc++.h>
//#define int long long
using namespace std;
const int N=5005,M=1e5+5;
int n,m,ans=2e9;
int head[N],ne[M<<1],from[M<<1],to[M<<1],w[M<<1],tot=0;
void add(int u,int v,int W)
{
   to[++tot]=v;
   from[tot]=u;
   w[tot]=W;
   ne[tot]=head[u];
   head[u]=tot;
}
struct node
{
   int id,v;
   bool operator<(const node &W) const
   {
   	return v>W.v;
   };
};
int first_dis[N],second_dis[N];
bool first_vis[N],second_vis[N];
int from_edg[N];
//标记每个点的最短路前驱以便找到最短路 
bool is[M<<1];
//is表示这条边在不在最短路里 
void first_dij()
{
   priority_queue<node> q;
   memset(first_dis,0x3f,sizeof(first_dis));
   first_dis[1]=0;
   q.push(node{1,0});
   while(!q.empty())
   {
   	node now=q.top();
   	q.pop();
   	if(first_vis[now.id]) continue;
   	first_vis[now.id]=true;
   	for(int i=head[now.id];i;i=ne[i])
   	{
   		if(first_dis[now.id]+w[i]<first_dis[to[i]])
   		{
   			from_edg[to[i]]=i;//在第一次跑dijkstra时记录前驱 
   			first_dis[to[i]]=first_dis[now.id]+w[i];
   			q.push(node{to[i],first_dis[to[i]]});
   		}
   	}
   }
}
void second_dij()
{
   priority_queue<node> q;
   memset(second_dis,0x3f,sizeof(second_dis));
   second_dis[n]=0;
   q.push(node{n,0});
   while(!q.empty())
   {
   	node now=q.top();
   	q.pop();
   	if(second_vis[now.id]) continue;
   	second_vis[now.id]=true;
   	for(int i=head[now.id];i;i=ne[i])
   	{
   		if(second_dis[now.id]+w[i]<second_dis[to[i]])
   		{
   			second_dis[to[i]]=second_dis[now.id]+w[i];
   			q.push(node{to[i],second_dis[to[i]]});
   		}
   	}
   }
}
void get_ans()
{
   int now=n;
   while(now)
   {
   	is[from_edg[now]]=true;
   	now=from[from_edg[now]];
   }
   for(int i=1;i<=tot;++i)
   {
   	if(is[i]) continue;
   	ans=min(ans,first_dis[from[i]]+w[i]+second_dis[to[i]]);
   }
}
int main()
{
   scanf("%d%d",&n,&m);
   int r1,r2,r3;
   for(int i=1;i<=m;++i)
   {
   	scanf("%d%d%d",&r1,&r2,&r3);
   	add(r1,r2,r3);
   	add(r2,r1,r3);
   }
   first_dij();
   second_dij();
   get_ans();
   printf("%d\n",ans);
   return 0;
}

标签:int,短路,first,笔记,second,P2865,now,id,dis
From: https://www.cnblogs.com/StevenZC/p/17085252.html

相关文章

  • (笔记)linux 之.service文件简介
     一、什么是.service文件?Linux中.service文件是某项服务对应的配置文件,可用于systemd管理和控制的服务的设置。.service文件通常包含3个模块,即[Unit]控制单元,表示启动......
  • 使用kubeadm安装k8s1.26.0笔记2
    一.安装版本Kubeadm使用cni方式安装版本:v1.26.0 二.机器准备1.机器规格本次安装1个master和1个node节点Master:192.168.64.6Node:192.168.64.7规则:CPU:2内存:4G系......
  • 读Java8函数式编程笔记08_测试、调试和重构
    1. Lambda表达式的单元测试1.1. 单元测试是测试一段代码的行为是否符合预期的方式1.2. Lambda表达式没有名字,无法直接在测试代码中调用1.2.1. 将Lambda表达式放入......
  • SpringBoot学习笔记 - 构建、简化原理、快速启动、配置文件与多环境配置、技术整合案
    【前置内容】Spring学习笔记全系列传送门:Spring学习笔记-第一章-IoC(控制反转)、IoC容器、Bean的实例化与生命周期、DI(依赖注入)Spring学习笔记-第二章-注解......
  • 「matlab学习笔记」MATLAB程序流程控制
    中国大学MOOC科学计算与MATLAB语言(点击此处跳转)MATLAB官方文档(点击此处跳转)3.1程序文件脚本文件和函数文件在MATLAB中程序文件的扩展名为.m,所以程序文件也称为M文件......
  • Per-Pixel Classification is Not All You Need for Semantic Segmentation论文阅读笔
    作者的解读:https://www.zhihu.com/search?type=content&q=MaskFormer摘要现有的语义分割方法将分割视为逐像素的分类,本文提出了MaskFormer,把分割转化为预测一系列的mask......
  • 离散化学习笔记
    本来应该配着一道题讲的因为太晚了就先咕咕了挖个坑虽然大概率应该不会填离散化简单来说就是当你需要用数组统计一些数的出现次数但数据范围过大(如1e9)无法使用数组存......
  • 线段树学习笔记
    本条目持续更新中线段树1:建树单点修改区间求和关于线段树:假如我们有这样一个数列33280721那我们就可以建一个线段树大概长这样:由图可知编号为i的左......
  • 数论笔记7-一元高次同余方程与多元同余方程
    这里我们先讨论一般情况(但一点也不简单,有很多厉害的定理),二次剩余之后再说.1.一元同余方程的具体解法我们考虑一般的一元同余方程\(f(x)\equiv0\pmodm\),容易......
  • 数论笔记汇总
    参考资料:潘承洞潘承彪《初等数论》(第三版)(主要,习题也是这上面的)闵嗣鹤严士健《初等数论》(第四版)(补充作用)大概评价一下两本书(个人主观).二潘的初等数......