最短路学习笔记

本文详细介绍了三种经典的图算法:Floyd算法用于求解多源最短路径,时间复杂度为O(n^3);Dijkstra算法适用于无负边情况,使用优先队列优化后复杂度为O((n+m)logn);Bellman-Ford算法能处理负边,可用于检测负权环。通过实例解析了每种算法的实现细节及应用场景。

三种算法
floyd
复杂度 :O(n^3)
应用场景:多源最短路,非负边
邻接矩阵存图

最短路

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
int n,m;
const int MAX_N = 105;
int d[MAX_N][MAX_N];
int main() {
	while(scanf("%d%d",&n,&m),n||m){
		memset(d,0x3f,sizeof(d));
		
		for(int i = 1;i <= n;i++)	d[i][i] = 0;
		for(int i = 1;i <= m;i++){
			int u,v,x;
			scanf("%d%d%d",&u,&v,&x);
			d[u][v] = min(d[u][v],x);
			d[v][u] = min(d[v][u],x);
		}
		
		for(int k = 1;k <= n;k++){
			for(int i = 1;i <= n;i++){
				for(int j = 1;j <=n;j++){
					d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
				}
			}
		}
		printf("%d\n",d[1][n]);
	}

	return 0;
}

dijkstra:
复杂度O(n^2),优先队列优化后O((n+m)logn)
应用场景:无负边
链式前向星存图
Til the Cows Come Home

#include <cstdio>
#include <queue>
#include <cstring>
#define min(x,y) x<y?x:y
#define P pair<int,int> 
using namespace std;
const int INF = 0x3f3f3f3f;
int n,m;
int tot = 0;
const int MAX_N = 1e3+5;
const int MAX_M = 2e3+10;
int d[MAX_N];
int edge[MAX_M<<1];
int ver[MAX_M<<1];
int Next[MAX_M<<1];
int head[MAX_M<<1];
void add(int x,int y,int z){
	ver[tot] = y;
	edge[tot] = z;
	Next[tot] = head[x];
	head[x] = tot++;
}
void init(){
	for(int i=1;i <= MAX_M;i++){
		head[i] = Next[i] = -1;
		
	}
	memset(d,0x3f,sizeof(d));
}
int main() {
	scanf("%d%d",&m,&n);
	init();
	for(int i = 1;i <= m;i++){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z);
		add(y,x,z);
	}
	
	priority_queue< P > q;//优先队列以pair第一维大到小排序,由最短路(最小值),所以放入(-d[i])
	d[n] = 0;
	q.push(P(0,n));
	while(q.size()){
		P p = q.top(); 	q.pop();
		int u = p.second;
		if(-p.first > d[u])continue;
		for(int i = head[u];~i;i = Next[i]){
			int v = ver[i],dis = edge[i];
			if(d[v] > d[u] + dis){
				d[v] = d[u] + dis;
				q.push(P(-d[v],v));
			}
		}
	}
	printf("%d",d[1]);
	return 0;
}

其中(-p.first > d[u])有另一种方式
用vis数组

if(vis[u])continue;
else {
	vis[u] = 1;
	...
	...
}

2021.7.13更新
今天学了Bellman-ford算法, 原因在于这道题
Currency exchange
题意是:有n种货币,给你一些某种货币, 你要不断的换钱,使自己的钱增加。而换币会有汇率和服务费。容易发现, 如果存在一个环, 通过不断地换币回到同一种货币, 若钱的数量增多, 则存在bug可以无限刷钱,输出Yes, 不然输出No
知识点:Bellman-ford算法和最长路
先讲Bellman-ford(没有队列优化)
代码如下

void Bellman(){
	memset(d, 0x3f, sizeof d);
	d[1] = 0;
	for(int i = 1; i <= n; i++){
		int flag = 0;
		for(int j = 1; j <= m; j++){
			int u = upoints[j], v = vpoints[j], w = cost[j];
			if(d[u] + w < d[v])
				d[v] = d[u] + w, flag= 1;
		}
		if(!flag)break;
	}
}

性质1:不存在负环的情况下, 有效更新最多进行n - 1次,计算的d[]就一定是最短路
解释:参考dijkstra算法, 边权为正数时,每次至少有一个点更新到最小值。
不同的是, bellman在有负边的情况下仍能正常工作, 只要不存在负环, 原因是是, 最短路一定是简单路径, 每次循环时, 能扩充出一个正确的点。

推论1:以最短路为例, 若第n次仍有边满足d[u] + w < d[v], 则存在负环, 最短路不可求

可以用队列优化:

void Spfa(){
	memset(d, 0x3f, sizeof d);
	d[1] = 0;
	que.push(1);
	vis[1] = 1;
	while(q,size()){
		int u = q.front();
		q.pop();
		vis[u] = 0;
		for(int i = head[u]; i; i = Next[i]){
			int v = ver[i], w = cost[i];
			if(d[u] + w < d[v]){
				d[v] = d[u] + w;
				if(!vis[v])vis[v] = 1, q.push(v);
			}
		}
	}
}

队列优化能用的原因仍可以用简单路径解释, 最短路上的第二个点离起点距离为1, 将所有距离为1的点更新完后, 再更新距离为2的点

知识点2:最长路
这个其实不难, 将不等号方向变相即可轻松实现。此时dijkstra不能判断正边, bellman可以判断有无正环

内容概要:本文档是一份关于交换路由配置的学习笔记,系统地介绍了网络设备的远程管理、交换机与路由器的核心配置技术。内容涵盖Telnet、SSH、Console三种远程控制方式的配置方法;详细讲解了VLAN划分原理及Access、Trunk、Hybrid端口的工作机制,以及端口镜像、端口汇聚、端口隔离等交换技术;深入解析了STP、MSTP、RSTP生成树协议的作用与配置步骤;在路由部分,涵盖了IP地址配置、DHCP服务部署(接口池与全局池)、NAT转换(静态与动态)、静态路由、RIP与OSPF动态路由协议的配置,并介绍了策略路由和ACL访问控制列表的应用;后简要说明了华为防火墙的安全区域划分与基本安全策略配置。; 适合人群:具备一定网络基础知识,从事网络工程、运维或相关技术岗位1-3年的技术人员,以及准备参加HCIA/CCNA等认证考试的学习者。; 使用场景及目标:①掌握企业网络中常见的交换与路由配置技能,提升实际操作能力;②理解VLAN、STP、OSPF、NAT、ACL等核心技术原理并能独立完成中小型网络搭建与调试;③通过命令示例熟悉华为设备CLI配置逻辑,为项目实施和故障排查提供参考。; 阅读建议:此笔记以实用配置为主,建议结合模拟器(如eNSP或Packet Tracer)动手实践每一条命令,对照拓扑理解数据流向,重点关注VLAN间通信、路由选择机制、安全策略控制等关键环节,并注意不同设备型号间的命令差异。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值