算法:Dijkstra最短路径算法

4 阅读2分钟

图论

存图

图分两种,一种是无向图,一种是有向图

B3643 图的存储

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e3+5;
ll mp1[N][N];
vector<ll> mp2[N];
ll n,m;
int main()
{
	cin>>n>>m;
	while(m--)
	{
		ll x,y;
		cin>>x>>y;
		mp1[x][y] = 1;
		mp1[y][x] = 1;
		//邻接矩阵存图
		mp2[x].push_back(y);
		mp2[y].push_back(x);
		//邻接表存图 
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			cout<<mp1[i][j]<<" ";
		
		cout<<"\n";
	}
	for(int i=1;i<=n;i++)
	{
		cout<<mp2[i].size()<<" ";
		sort(mp2[i].begin(),mp2[i].end());
		
		for(int j=0;j<mp2[i].size();j++)
			cout<<mp2[i][j]<<" ";
		
		cout<<"\n";
	}
	return 0;
}

最短路径算法 dijkstra 视频讲解

Dijkstra最短路径算法

Dijkstra算法算是贪心思想实现的,首先把起点到所有点的距离存下来找个最短的,然后松弛一次再找出最短的,所谓的松弛操作就是,遍历一遍看通过刚刚找到的距离最短的点作为中转站会不会更近,如果更近了就更新距离,这样把所有的点找遍之后就存下了起点到其他所有点的最短距离,下面仔细讲。

参数解释:

Chara数组 :储存两点间的距离,Chara[i][j]的值就是点i到点j的距离。 dis数组:储存起点到各个点的距离,dis[i]就是起点到i点的距离。 vis数组:标记点是否访问过 INF:宏定义的最大值路不通

算法思想

有两个数组,dis和vis含义参见上面,初始时vis中只有起点,更新dis中的起点到所有点的距离. 遍历所有节点,找到距离起点最近的一个点K,将这个点加入vis中标记 进行松弛操作,遍历没有在vis数组中的其他所有点,比较起点——>该点和起点——>K点——>该点的距离, 重复2-3操作,直到所有的点遍历完

#define INF 65535
int n,m,s,t;
int Chara[N][N],dis[N],vis[N],p[i];

void Dijkstra(int src)  //src传入的起点
{
	for(int i=0; i<m; i++) //初始化起点到所有点的距离
	{
		dis[i] = Chara[src][i];
		vis[i] = 0;
		p[i]=0;
	}
	dis[src] = 0; //到自身距离为0
	vis[src] = 1; //标记 注src=0
	for(int i=0; i<m; i++)
	{
		int ans = INF,k;
		for(int j=0; j<m; j++) // 寻找未被访问过距离起点v0最近的
		{
			if(!vis[j] && dis[j] < ans)
			{
				k = j;
				ans = dis[j];
			}
		}
		vis[k] = 1;   //标记已访问
		if(ans == INF) break; //表示剩下所有点都不通
		for(int j =0; j<m; j++)  //松弛操作,更新起点到所有未访问点的距离
		{
			if(!vis[j] &&  dis[k] + Chara[k][j]<dis[j] )
			{
				dis[j] = dis[k] + Chara[k][j];
				p[j]=k;//存放前驱节点
			}
		}
	}
}

Dijkstar算法