图总结

1.思维导图

2.笔记

Dijkstra算法

要求:边权非负

思路:顶点分为两组,一旦确定了某点的最短路径就放入第一组,其余归为第二组;每次取能够到的最短的那条路径。

具体实现:每次加入第一个组时更新第二组的距离值,选取距离值最小的顶点加入第一组

设置length数组和pre数组

复杂度:没有最小堆:O(V2+E),最小堆不删除旧值:O((|V|+|E|)log|E|)

Floyd算法

要求:允许边权值为负

每次算出从某点到某点中间顶点序号不大于K的最短路径长度,n次以后包括了所有最终的最短路径。

设置path数组(初始-1)和adj数组

复杂度:O(n3)

Prim算法

思路:贪心

从任意一点开始,把这个点包括在MST里,对一个点在MST中而另一个不在的边取出最小的放进MST

复杂度同Dijkstra

Kruskal算法

将所有边分成很多等价类,连通后就成为同一个等价类,按权值大小顺序处理每一条边,该边连接不同等价类就加到MST

复杂度O(|E|log|E|)(堆排序时间)

拓扑排序

不唯一

基本思想,判断环路(bfs和dfs,dfs不能判断环)

复杂度:相邻矩阵O(|V|3),邻接表:O(2|V|+|E|)

Dfs

邻接表代价有向图O(|V|+|E|) 无向图O(|V|+2|E|) 相邻矩阵O(|V|2)

BFS

复杂度与dfs相同

3.代码

题目:7-2 六度空间

image

解答代码:

#include <windows.h>
#include<iostream>
#include<queue>
using namespace std;
#define max 1001
int  n, m;
int a[1001][1001] = { 0 };
int vis[1001] = { 0 };
int bfs(int x)
{
	memset(vis, 0, sizeof(vis));
	int t = 0, cnt = 1;
	queue<int>q;
	vis[x] = 1;
	q.push(x);
	int k = 1;
	while (!q.empty())
	{
		int v = 0;
		for (int j = 1; j <= k; j++)
		{
			int temp = q.front();
			q.pop();
			for (int i = 1; i <= n; i++)
			{
				if (!vis[i] && a[temp][i])
				{
					vis[i] = 1;
					q.push(i);
					cnt++;
					v++;
				}
			}
		}
		k = v;
		t++;
		if (t == 6)
			break;
	}
	return cnt;
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int b, c;
		cin >> b >> c;
		a[b][c] = a[c][b] = 1;
	}
	for (int i = 1; i <= n; i++)
	{
		cout << i << ": ";
		printf("%.2lf", bfs(i) * 100.0 / n);
		cout << "%" << endl;
	}
}

结果:

image

posted @ 2021-05-30 12:30  lCiZrno  阅读(63)  评论(0)    收藏  举报