C++实现SPFA和dijikstr算法

看了B站上卿学姐的视频,学着写了写

先是SPFA:

 

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int maxz = 205;
vector<pair<int, int>>E[maxz];
int inq[maxz], dis[maxz];
int n, m;
void inti()//初始化领接表
{
	for (int i = 0; i < maxz; ++i) E[i].clear();//先清空每一个vector<pair<int,int>>
	for (int i = 0; i < maxz; ++i) inq[i] = 0;//再清空点队列
	for (int i = 0; i < maxz; ++i)dis[i] = 1e9;//再初始化距离数组
}
int main()
{
	inti();//初始化
	while (cin >> n >> m)//n为点数,m为边数
	{
		for (int i = 1; i <= m; ++i)//先初始化每条边
		{
			int x, y, k;//点x,点y,距离k
			scanf("%d%d%d", &x, &y, &k);
			E[x].push_back(make_pair(y, k));//将x到y的边的长度更新为k
			E[y].push_back(make_pair(x, k));//将y到x的边的长度也更新为k
		}//完成领接表的建立
		int s, t;//起点s和终点t
		queue<int> q;//用于优化算法的队列q
		q.push(s);//先将起点s入队
		inq[s] = 1;//再记录起点s已入队
		dis[s] = 0;//s到s的距离当然为0
		while (!q.empty())//如果队列不为空的话
		{
			int now;
			now = q.front();//取队列中的第一个元素
			q.pop();//队首元素出队
			inq[now] = 0;//记录出队
			for (int i = 1; i <= E[now].size(); ++i)//通过我们出队的这个点来更新对每个点的路径权值
			{
				int v = E[now][i].first;//记录now-v中的v
				if (dis[v] > dis[now] + E[now][i].second)//如果以前从s到v点的距离大于了先经过now点再到v点的距离
				{
					dis[v] = dis[now] + E[now][i].second;//那就更新dis[v]
					if (inq[v] == 1)continue;//如果v点已经在队列中,则不作操作
					else inq[v] = 1, q.push(v);//否则将v点加入队列中
				}

			}
		}
		if (dis[t] == 1e9)printf("-1");//如果还是到不了,则寻找最短路失败
		else printf("%d\n", dis[t]);//否则输出找到的最短路的值
	}
	return 0;
}


再是dijikstr:

 

 

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int maxz = 205;
vector<pair<int, int>>E[maxz];
int dis[maxz];
int n, m;
void inti()//初始化领接表
{
	for (int i = 0; i < maxz; ++i) E[i].clear();//先清空每一个vector<pair<int,int>>
	for (int i = 0; i < maxz; ++i)dis[i] = 1e9;//再初始化距离数组
}
int main()
{
	inti();//初始化
	while (cin >> n >> m)//n为点数,m为边数
	{
		for (int i = 1; i <= m; ++i)//先初始化每条边
		{
			int x, y, k;//点x,点y,距离k
			scanf("%d%d%d",&x,&y,&k);
			E[x].push_back(make_pair(y, k));//将x到y的边的长度更新为k
			E[y].push_back(make_pair(x, k));//将y到x的边的长度也更新为k
		}//完成领接表的建立
		int s, t;//起点s和终点t
		priority_queue<pair<int,int>> q;//用优先队列
		dis[s] = 0;//s到s的距离当然为0
		q.push(make_pair(-dis[s],s));//优先队列优先级最高的是最大的元素,我们存的时候取反,于是优先级最高的元素就成为了原本最大的元素,也即离选定起点最近的元素
		while (!q.empty())//如果队列不为空的话
		{
			int now;
			now = q.top().second;//取队列中的第一个元素
			q.pop();//队首元素出队
			for (int i = 0; i < E[now].size(); ++i)//通过我们出队的这个点来更新对每个点的路径权值
			{
				int v = E[now][i].first;//记录now-v中的v
				if (dis[v] > dis[now] + E[now][i].second)//如果以前从s到v点的距离大于了先经过now点再到v点的距离
				{
					dis[v] = dis[now] + E[now][i].second;//那就更新dis[v]
					q.push(make_pair(-dis[v],v));//讲用到的点更新进队列,由于选择的点都是按照距离最近来选取的,所以不用担心之后会重复入队
				}
			}
		}
		if (dis[t] == 1e9)printf("-1");//如果还是到不了,则寻找最短路失败
		else printf("%d\n",dis[t]);//否则输出找到的最短路的值
	}
	return 0;
}

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值