蓝桥杯day9——树和图的DFS&&BFS


链表模拟数组

看本篇需要了解,链表的数组模拟

图和树的存储

  1. 邻接矩阵,空间是 O ( n 2 ) O(n^2) O(n2)
  2. 一般使用邻接表来存储
    • 数据结构

      h[N]:表头,每个节点的连通的起始点
      e[M]:存储节点的值
      ne[M]:对应e[M],next指针的作用
      idx:用于节点迭代

    • 方法:用于构建图和树

      ##@parm a, b,值为a的节点通往b节点
      def add(a, b) :
      	global idx
      	e[idx] = b
      	ne[idx] = h[a]
      	h[a] = idx
      	idx += 1
      

DFS

模板
def dfs(u) :
	st[u] = True # 记录该节点已经被遍历过了
	i = h[u] # 取出正在遍历节点的表头指针
	while i != -1 : # 通过指针迭代层级角度迭代
		j = e[i]
		if not st[j] : 
		    dfs (j) # 深入下一个节点
		i = ne[i]
例题:树的重心

给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。

请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

输入格式
第一行包含整数 n,表示树的结点数。

接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。

输出格式
输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。

数据范围
1≤n≤10^5
输入样例
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
输出样例:
4

N = 100010
M = N * 2
h = [-1] * N
e = [-1] * M
ne = [-1] * M
idx = 0

def add(a, b) :
	global idx
	e[idx] = b
	ne[idx] = h[a]
	h[a] = idx
	idx += 1
ans = N
st = [False] * N
def dfs(u) :#对节点u进行搜索,返回以u为根节点连通块的数量
	global ans
	size, sum = 0, 1#size记录u的连通分支的最大数量,sum记录以u为根节点连通块数量
	st[u] = True
	i = h[u]
	while i != -1 :
		j = e[i]
		i = ne[i]
		if st[j] : continue#说明j节点的所有分支已经被计算过,这里是它的父节点
		s = dfs (j)#连通分支的节点个数
		size = max(s, size)
		sum += s
	size = max(size, n - sum)#考虑非子节点的连通分支
	ans = min(size, ans)
	return sum
	
n = int(input())
for i in range(n - 1) :	
	a, b = map(int, input().split())
	add(a, b)
	add(b, a)

dfs(1)

print(ans)

e[i] 存储的是第i个节点的标号,一般来说其值是惟一的标定一个节点,一般操作和遍历都是以其值作为标准的,通过h和ne来记录位置,e来进行操作
通过st数组来记录节点是否被访问过

BFS

模板
def bfs() :
	que = collections.deque()
	d = [-1] * N
	que.appendleft(1)
	d[1] = 0
	while len(que) :
		t = que.pop()
		i = h[t]
		while i != -1 :
			j = e[i]
			i = ne[i]
			if d[j] == -1 :
				d[j] = d[t] + 1
				que.appendleft(j)
	return d[n]
例题:图中点的层次

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环。

所有边的长度都是 1,点的编号为 1∼n。

请你求出 1 号点到 n 号点的最短距离,如果从 1 号点无法走到 n 号点,输出 −1。

输入格式
第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 a 和 b,表示存在一条从 a 走到 b 的长度为 1 的边。

输出格式
输出一个整数,表示 1 号点到 n 号点的最短距离。

数据范围
1≤n,m≤10^5
输入样例:
4 5
1 2
2 3
3 4
1 3
1 4
输出样例:
1

import collections

N = 100010
M = 2 * N
h = [-1] * N
e = [-1] * M
ne = [-1] * M
idx = 0

def add(a, b) :
	global idx
	e[idx] = b
	h[b] = h[a]
	h[a] = idx
	idx += 1
def bfs() :
	que = collections.deque()
	d = [-1] * N
	que.appendleft(1)
	d[1] = 0
	while len(que) :
		t = que.pop()
		i = h[t]
		while i != -1 :
			j = e[i]
			i = ne[i]
			if d[j] == -1 :
				d[j] = d[t] + 1
				que.appendleft(j)
	return d[n]

n, m = map(int, input().split())
for i in range(m) :
	a, b = map(int, input().split())
	add(a, b)
print(bfs())

总结

数组模拟领接表存储图和树的操作还得多做做,熟能生巧。需要注意:
e标志着实际的节点,h和ne都是起着模拟链表指针的作用。

posted @   chanxe  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示