首页 > 其他分享 >图论(未完成)

图论(未完成)

时间:2023-06-17 22:34:49浏览次数:34  
标签:图论 pq int 短路 源点 完成 pair dis

-1.最短路径

-1.1 Bellman-Ford

Bellman-Ford 是一种最基础的求解单源最短路径的算法,其整体思想是暴力,但是用途十分广泛。

具体实现中,该算法将 \(m\) 条边松弛 \(n - 1\) 次,其中松弛是指对于一条边 \((x, y)\),如果 \(dis_x + w_{x, y} < dis_y\),那么将 \(dis_y\) 的值修改为 \(dis_x + w{x, y}\),意思是如果当前从源点到 \(x\) 的最短路径加上 \((x, y)\) 的边权小于从源点到 \(y\) 的最短路径,那么就找到了一条比原来终点为 \(y\) 的最短路径更短的路径,那么更新。

正确性证明:在一个有 \(n\) 个点的图中,任意两点的最短路至多经过 \(n - 1\) 条边,故至多只需松弛 \(n - 1\) 次。详细证明这里不再阐述。

同时,Bellman-Ford 算法还可以处理有负权边的图的最短路,并且可以判断负环。

但是此算法由于其时间复杂度过高,为 \(\Theta(nm)\),所以选手一般不使用 Bellman-Ford,而是使用其队列优化版本 SPFA,后文将会详细阐述。

核心代码:

for(int i = 1; i < n; i++)//枚举n - 1轮
	for(int j = 1; j <= m; j++)//枚举每一条边
	{
		int x = e[j].x, y = e[j].y, w = e[j].w;
		if(dis[x] + w < dis[y])//松弛操作
			dis[y] = dis[x] + w;
	}

-1.2 Dijkstra

Dijkstra 是一种基于贪心的一种单源最短路径算法,其整体思想是蓝白点

在算法实现中, 首先将起点标记为蓝点(求出最短路径的点,反之则白点),然后循环 \(n - 1\),对于每一次循环,找出当前所有点中距离源点的最短路最小且是白点的点 \(x\),然后枚举点 \(x\) 的每一个邻接点 \(y\),进行松弛操作,如果 \(dis_x + w_{x, y} < dis_y\),那么 \(dis_y\) 更新为 \(dis_x + w{x, y}\),并且标为蓝点

关于正确性,此处引用@Alex_Wei初级图论中的正确性证明。

归纳假设已经松弛过的节点 \(p_1, p_2, ..., p_{k - 1}\) 在扩展时均取到了其最短路。\(p_k\) 为没有被扩展的 \(dis\) 最小的节点。

\(p_k\) 的最短路一定由 \(p_i(1 \le i < k)\) 的最短路扩展而来,不可能出现 \(dis_{p_i}+w_{p_i,p_k+1}+w_{p_k + 1, p_k} < dis_{p_j} + w_{p_j, p_k}(1 \le i,j < k)\) 的情况。否则由于边权非负,\(w_{p_k + 1, p_k} \le 0\),所以 \(dis_{p_i} + w_{p_i, p_k + 1} < dis_{p_j} + w_{p_j, p_k}\),即当前 \(dis_{p_k + 1} < dis_{p_k}\),与 \(dis_{p_k}\)
的最小性矛盾。

初始令源点 \(s\) 的 \(dis_s\) 为 \(0\) ,假设成立,因此算法正确。

此时该算法的时间复杂度为 \(\Theta(n^2)\),显然是很慢的,在稀疏图中,还不如可以处理负权边的 Bellman-Ford,所以我们需要优化。

在寻找距离源点的最短路最小的白点时,一个一个找显然很慢,而这里我们可以使用小根堆优化。松弛的时候,只要条件成立,就将这个点压入堆中,然后将这些点一个一个取出对它的邻接点进行松弛。

这里的大根堆可以使用 STL 中的 priority_queue (优先队列)来实现。由于我们需要存储边权和终点,所以优先队列就需要存储 \(2\) 个变量。这里这里介绍 \(2\) 种方法。

\(1\). 重载运算符。定义结构体类型的优先队列,然后重载 <

代码:

struct Node
{
	int x, w;
	bool operator < (const Node &b)const//重载运算符
	{
		return w > b.w;
	}
};
priority_queue<Node> pq;

\(2\). pair。定义一个 pair<int, int>类型的优先队列,按照第一个值从大到小排序。

代码:

priority_queue< pair<int, int> > pq;//定义一个pair<int, int>类型的优先队列。
pq.push(make_pair(-dis[y], y));//插入一条边,边权为dis[i],终点为y,由于默认从大到小排序,所以边权要取负
int x = pq.top().second;//取出一个点

相对来说 pair 要好写一些,这里更加推荐 pair

此时的时间复杂度降为 \(\Theta(m \log m)\),十分优秀。

模板题P4779 【模板】单源最短路径(标准版)代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5 + 5;
int n, m, s, dis[N];
bool vis[N];
struct node
{
	int y, w;
};
vector<node> e[N];
void dijkstra(int s)
{
	for(int i = 1; i <= n; i++)//将dis赋为极大值
		dis[i] = INT_MAX;
	priority_queue< pair<int, int> > pq;
	pq.push(make_pair(0, s));//将源点入队
	dis[s] = 0;//源点到源点的距离为0
	while(!pq.empty())
	{
		int x = pq.top().second;
		pq.pop();
		if(vis[x])//如果是蓝点,那么跳过
			continue;
		vis[x] = true;//标记为蓝点
		int len = e[x].size();
		for(int i = 0; i < len; i++)
		{
			int y = e[x][i].y, w = e[x][i].w;
			if(dis[x] + w < dis[y])//松弛操作
			{
				dis[y] = dis[x] + w;
				pq.push(make_pair(-dis[y], y));//入队
			}
		}
	}
	return;
}
signed main()
{
	cin >> n >> m >> s;
	for(int i = 1; i <= m; i++)
	{
		int x, y, w;
		cin >> x >> y >> w;
		e[x].push_back({y, w});//建边
	}
	dijkstra(s);
	for(int i = 1; i <= n; i++)
		cout << dis[i] << " ";
	return 0;
}

标签:图论,pq,int,短路,源点,完成,pair,dis
From: https://www.cnblogs.com/Sunseeker-Foam/p/17488379.html

相关文章

  • 项目-已完成
    ERPerp_parent(Java-后端)erp_web(Java-前端)视频点播VIDEO_Parent(Java-后端)VIDEO_Portal(Nuxt-商户端)JavaScript/HTML/CSSNubia(努比亚-网站)Qunar(去哪儿-移动官网静态页面,采用伸缩布局)Heroes-Of-The-Storm(风暴英雄游戏网站,静态页面)VIVO(VIVO-网站,响应式)......
  • 【图论】割点与桥
    目录定义割点割边(桥)关系算法求割点伪代码模版定义割点如果删除无向图中的某个点会使无向图的连通分量数增多,则把这个点称为割点。割边(桥)如果删除无向图中的某条边会使无向图的连通分量数增多,则把这个点称为割边(桥)。关系桥的两端可以有割点。算法求割点割点:存在子树最高......
  • WhaleStudio 完成与偶数科技云原生分布式数据库 OushuDB 的产品兼容性认证
    近日,白鲸开源「WhaleStudiov2.0」已通过与北京偶数科技产品云原生分布式数据库OushuDBv5.0的相互兼容性测试,并获得授权证书。白鲸开源与偶数科技的联合测试结果显示,经过产品的功能、兼容性测试,WhaleStudiov2.0在云原生分布式数据库OushuDBv5.0上整体运行稳定,满足功能及......
  • 【回调详解】内核回调的详细图解【未完成】
    1、进程回调进程回调是内核下的全局变量,存放到PspCreateProcessNotifyRoutine中,该变量是个数组;该数组中已经存放函数的具体个数,则存放到全局变量PspCreateProcessNotifyRoutineCount中。PspCreateProcessNotifyRoutine的最大值由一个宏决定:PSP_MAX_CREATE_PROCESS_NOTIFY。1.1......
  • ajax + java 实现类似网易邮箱邮件地址自动完成功能
    ajax+java实现类似网易邮箱邮件地址自动完成功能2008-04-0218:30********************************************************************源代码下载链接:http://www.javaeye.com/topic/150778***************************************************************......
  • 时域线性粘弹性(待完成)
    Boltzmann叠加原理对于蠕变,有\(\gamma(t)=J(t)\sigma\),其中\(J(t)=J_g+J_d\Psi(t)\)。假设在各个时间节点上施加一些列的\(\Delta\sigma(\tau_i)\)外界激励,系统的一系列响应是\(J(t-\tau_i)\),相乘并累加得到下式,当间隔很小时,或者是说外加的激励是一个连续变化的值的时候,......
  • 基于Consul完成腾讯云主机监控
    基于Consul完成腾讯云主机监控目录基于Consul完成腾讯云主机监控背景构成流程数据POST至ConuslPrometheus抓取Consul注册主机背景腾讯云提供tencent-exporter支持获取CVM主机列表及监控信息。但碍于CVM主机过多,使用Tencent-exporter将导致频繁调用腾讯云API,导致额外费用支持。......
  • 使用iPhone相机和OpenCV来完成3D重建(第三部分)
    正文字数:4509 阅读时长:2分钟欢迎来到本教程的第三部分,也是最后一部分关于立体重建的教程。Postedby OmarPadierna url: https://medium.com/@omar.ps16/stereo-3d-reconstruction-with-opencv-using-an-iphone-camera-part-iii-95460d3eddf0快速回顾:在第一部分中,我们简要介......
  • 使用iPhone相机和OpenCV来完成3D重建(第一部分)
    正文字数:1497 阅读时长:2分钟这个教程将带你使用自己的手机摄像头和图片实现从零开始到点云。Postedby OmarPadierna https://becominghuman.ai/stereo-3d-reconstruction-with-opencv-using-an-iphone-camera-part-i-c013907d1ab5这是一个由3部分组成的系列文章。我注意到,其......
  • 轻量级报表解决方案Telerik Reporting,轻松完成嵌入式报表交互!
    开发者可以通过多种方式与集成在应用程序中的Telerik报表进行交互,从“只是阅读它”到更改报表中包含的数据。但是要注意:开发者所能做的一些事情将取决于报表是如何创建的,以及它是如何嵌入到应用程序UI中的。因此(和任何应用程序一样),为了从Telerik报表中获得想要的,开发团队尽量要......