Dijkstra算法+邻接表存储

学习视频:8.3 图的邻接表存储(1)——信息学奥赛培训课程_哔哩哔哩_bilibili

                  8.3 图的邻接表存储(2)——信息学奥赛培训课程_哔哩哔哩_bilibili

                  8.11 最短路 Dijkstra 算法——信息学奥赛培训课程_哔哩哔哩_bilibili

题目:P3371 【模板】单源最短路径(弱化版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

           P4779 【模板】单源最短路径(标准版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include<bits/stdc++.h>
using namespace std;
/*邻接表存储*/
const int maxn = 500005;
int num;
int Head[maxn];//起点为i的点指向与之相连的当前边的编号
int To[maxn];//编号为i的边的终点
int W[maxn];//编号为i的边的权值
int Next[maxn];//同属于一个起点的下一条边的编号为i的边
int n, m, s;//给定一个n个点,m条有向边的带非负权图,请你计算从s出发
void addEdge(int v, int u,int w)//添加一条从v到u权值为w的有向边
{
	num++;
	Next[num] = Head[v];
	To[num] = u;
	W[num] = w;
	Head[v] = num;
}
int D[maxn];//距离起点的距离
int Blue[maxn];//标记蓝白点
void Dijkstra(int s)//s是起点
{
	const int oo = 1e9 + 5;
	for (int i = 1; i <= n; i++)
		D[i] = oo;
	D[s] = 0;
	for (int i = 1; i <= n; i++)
	{
		int minn = oo, k = 0;
		/*从蓝点中找出距离s最近的点*/
		for (int j = 1; j <= n; j++)
		{
			if (!Blue[j] && D[j] < minn)
			{
				minn = D[j];
				k = j;
			}
		}
		Blue[k] = 1;//找到距离s最近的点k后标记为白点
		for (int j = 1; j <= n; j++)
		{
			//if(D[k] + k到j的距离 < D[j])更新D[j]
			int c = Head[k];
			while (c)//看看k到j有没有直接的路径
			{
				if (To[c] == j)
				{
					if (D[k] + W[c] < D[j])
						D[j] = D[k] + W[c];
				}
				c = Next[c];
			}
		}
	}
}
int main(void)
{
	cin >> n >> m >> s;
	for (int i = 1; i <= m; i++)
	{
		int a, b, c;
		scanf_s("%d%d%d", &a, &b, &c);
		addEdge(a, b, c);
	}
	Dijkstra(s);
	for (int i = 1; i <= n; i++)
		printf("%d ", D[i]);
	return 0;
}
#include<bits/stdc++.h>
using namespace std;
int visit[10];
const int MAX_VERTEX = 10;//图的最大顶点数
struct VertexNode {
	int Vertex;//终点
	VertexNode* next;//指向下一个终点
};
class ALGraph
{
private:
	VertexNode FirstVerList[MAX_VERTEX];//顶点表
	int VertexNum, EdgeNum;//边的数目,顶点的数目
public:
	ALGraph(int map[][2],int n,int m);//* map[2]传入各个顶点的编号,n是顶点数目,m是边的数目
	VertexNode* GetFirstVerList();//输出顶点表地址
	void DFS(int v);
	bool IsRoot(int v);
	void RefreshVisit();//将visit数组重置为0
	void BFS(int v);
};
ALGraph::ALGraph(int map[][2], int n, int m)
{
	VertexNum = n;
	EdgeNum = m;
	for (int i = 1; i <= VertexNum; i++)//初始化顶点表
	{
		FirstVerList[i].Vertex = i;
		FirstVerList[i].next = NULL;
	}
	for (int i = 1; i <= EdgeNum; i++)
	{
		int vi = map[i][0], vj = map[i][1];
		VertexNode* point = new VertexNode;
		point->Vertex = vj;
		point->next = FirstVerList[vi].next;
		FirstVerList[vi].next = point;
	}
}
VertexNode* ALGraph::GetFirstVerList()
{
	return FirstVerList;
}
void ALGraph::DFS(int v)
{
	visit[v] = 1;
	//cout << v << ' ';
	for (VertexNode* p = FirstVerList[v].next; p != NULL;p=p->next)//结点存在
	{
		if(visit[p->Vertex]==0)
		DFS(p->Vertex);
	}
}
bool ALGraph::IsRoot(int v)//利用深度优先搜索判断结点v是不是根
{
	DFS(v);
	for (int i = 1; i <= VertexNum; i++)
	{
		if (visit[i] == 0)
			return false;
	}
	return true;
}
void ALGraph::RefreshVisit()
{
	for (int i = 1; i <= VertexNum; i++)
		visit[i] = 0;
	return;
}
void ALGraph::BFS(int v)
{
	queue<int> qu;
	qu.push(v);
	visit[v] = 1;
	cout << v << ' ';
	while (!qu.empty())
	{
		int NewPoint;
		NewPoint = qu.front(); qu.pop();
		VertexNode* w = FirstVerList[NewPoint].next;
		while (w != NULL && visit[w->Vertex] == 0)
		{
			visit[w->Vertex] = 1;
			cout << w->Vertex << ' ';
			qu.push(w->Vertex);
			w = w->next;
		}
	}
}

#include<iostream>
#include "ALGraph.h"
using namespace std;
int A[6][6] =//邻接矩阵
{
	0,1,1,0,0,0,
	0,0,0,1,1,0,
	0,0,0,0,0,1,
	0,1,0,0,0,0,
	0,1,0,0,0,0,
	0,0,1,0,0,0
};
//int map[15][2] =
//{
//	{1,3},{2,3},{2,4},{2,6},{3,6},{4,5},{4,6},{5,1},{6,1},{6,5}//有向图
//};
int mapp[15][2];
int EDGE;
void Change()//将邻接矩阵转化为map[][]形式
{
	for (int i = 0; i < 6; i++)
	{
		for (int j = 0; j < 6; j++)
		{
			if (A[i][j] == 1)
			{
				mapp[++EDGE][0] = i + 1;
				mapp[EDGE][1] = j + 1;
			}
		}
	}
}
int main(void)
{
	Change();//第一问将邻接矩阵转化为map[][]形式
	ALGraph ALG(mapp,6,EDGE);
	for (int i = 1; i <= 6; i++)
	{
		if (ALG.IsRoot(i) == 1)
		{
			cout << "结点" << i << "是根结点" << endl;
			ALG.RefreshVisit();
		}
	}
	ALG.RefreshVisit();
	ALG.BFS(1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值