P8802 [蓝桥杯 2022 国 B] 出差

P8802 [蓝桥杯 2022 国 B] 出差

分析

很明显:单源最短路径 + 没有负权边 = dijkstra

1.存图

2.准备两个数组

dis[]:更新源点到各个点的距离

vis[]:标记是否访问

3.从源点开始,更新源点到与其邻接的点的距离,每次选出dis[]min且未访问的点进行重复上述步骤

代码

两种实现方法:

1.链式前向星存图 + prioroty_queue

注意:优先队列默认大根堆,故要重载 < ;且优先队列按优先级排序,对于 < 而言,a < b为true的意思是,右边的优先级大于左边,故应为return a > b;

cpp 复制代码
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;

typedef long long ll;
const int N = 1010,M = 10010;
struct Node{
	int u,dis;
    
    //重载 <(优先队列默认大根堆)
	bool operator < (const Node &x)const
	{
		return dis > x.dis;
	}
};
//链式前向星
struct edges{
	int to;
	int ne;
	int w;
}e[M*2];
int head[N],cnt = 1,n,m,c[N];
ll dis[N];
bool vis[N];
priority_queue<Node> q;

//初始化
void init()
{
	memset(head,-1,sizeof head);
	memset(dis,0x3f,sizeof dis);
}
//加边
void add(int u,int v,int w)
{
	e[cnt].to = v;
	e[cnt].ne = head[u];
	e[cnt].w = w;
	head[u] = cnt ++;
}
//dijkstra模板
void dijkstra(int x)
{
	dis[x] = 0;
	q.push((Node){x,0});
	while(!q.empty())
	{
		Node t = q.top();
		q.pop();
		int u = t.u;
		if(vis[u]) continue;
		vis[u] = 1;
		for(int i = head[u];i != -1;i = e[i].ne)  //遍历邻接点
		{
			int v = e[i].to;
			int w = e[i].w;
			if(dis[v] > dis[u] + w)  //更新dis[]
			{
				dis[v] = dis[u] + w;
				if(!vis[v]) q.push((Node){v,dis[v]});  //未被访问,压入队列
			}
		}
	}
}

int main()
{
	init();
	scanf("%d %d",&n,&m);
	for(int i = 1;i <= n;i ++) scanf("%d",&c[i]);
	for(int i = 1;i <= m;i ++)
	{
		int u,v,w;
		scanf("%d %d %d",&u,&v,&w);
		add(u,v,w + c[v]);  //把隔离时间当边权值
		add(v,u,w + c[u]);
	}
	dijkstra(1);
	printf("%lld",dis[n] - c[n]);  //减去最后一个城市的隔离时间
	return 0;
}

2.邻接矩阵存图 + 一重循环(高举y总大旗!超简洁!)

cpp 复制代码
#include<iostream>
#include<cstring>
using namespace std;

typedef long long ll;
const int N = 1010;
int g[N][N],n,m,c[N];
ll dis[N];
bool vis[N];

void dijkstra()
{
	memset(dis,0x3f,sizeof dis);
	dis[1] = 0;
    //重复分析中的第三步n-1次即可
	for(int i = 1;i < n;i ++)
	{
        //找到dis[]中的min且未被访问
		int t = 0;  //初始化dis[]为0x3f,t = 0时,dis[t] = max
		for(int j = 1;j <= n;j ++)
		{
			if(!vis[j] && dis[t] > dis[j]) t = j;
		}
        //找到t,用t更新dis[]
		for(int j = 1;j <= n;j ++)
		{
			if(dis[j] > dis[t] + g[t][j])
				dis[j] = dis[t] + g[t][j];
		}
		vis[t] = true;  //记得标记一下已访问
	}
	return ;
}

int main()
{
	memset(g,0x3f,sizeof g);  //初始化g[][]
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n;i ++) scanf("%d",&c[i]);
	for(int i = 1;i <= m;i ++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		g[x][y] = z + c[y];
		g[y][x] = z + c[x];  //存双向边 + c[x]
		
	}
	dijkstra();
	printf("%lld",dis[n] - c[n]);
	return 0;
}
相关推荐
CodeByV7 分钟前
【算法题】堆
算法
kaikaile199516 分钟前
A星算法避开障碍物寻找最优路径(MATLAB实现)
数据结构·算法·matlab
今天_也很困31 分钟前
LeetCode 热题100-15.三数之和
数据结构·算法·leetcode
企业对冲系统官1 小时前
基差风险管理系统日志分析功能的架构与实现
大数据·网络·数据库·算法·github·动态规划
ldccorpora1 小时前
GALE Phase 1 Chinese Broadcast News Parallel Text - Part 1数据集介绍,官网编号LDC2007T23
人工智能·深度学习·算法·机器学习·自然语言处理
千金裘换酒1 小时前
LeetCode 数组经典题刷题
算法·leetcode·职场和发展
fie88892 小时前
MATLAB有限元框架程序
python·算法·matlab
小郭团队2 小时前
1_5_五段式SVPWM (传统算法反正切+DPWM1)算法理论与 MATLAB 实现详解
人工智能·嵌入式硬件·算法·dsp开发
思成Codes2 小时前
ACM训练:接雨水3.0——动态接雨水
数据结构·算法
alphaTao2 小时前
LeetCode 每日一题 2026/1/12-2026/1/18
python·算法·leetcode