图的遍历
1013. Battle Over Cities (25)-PAT甲级真题(图的遍历,统计强连通分量的个数,dfs)
1021. Deepest Root (25)-PAT甲级真题(图的遍历,dfs,连通分量的个数)
1034. Head of a Gang (30)-PAT甲级真题(图的遍历dfs)
1076. Forwards on Weibo (30)-PAT甲级真题(图的遍历bfs)
分析
难度:1034=1076>1021>1013
P1013
题目大意:给出n个城市之间有相互连接的m条道路,当删除一个城市和其连接的
道路的时候,问其他几个剩余的城市至少要添加多少个路线才能让它们重新变
为连通图
分析: 题目意思很简单,但是初学者可能觉得很难,我一开始就在想将删除城市
标记为false,其边设置为INF,是不是要重新拷贝一份地图,毕竟K次查询,DFS
添加边的话,什么条件下添加,死胡同肯定也不对。但是实际上题目真得很简单
,没必要想的那么复杂。实质上就是考你一张图连通块的个数。
水题
P1021
题目大意:给出n个结点(1~n)之间的n条边,问是否能构成一棵树,如果不能
构成则输出它有的连通分量个数,如果能构成一棵树,输出能构成最深的树
的高度时,树的根结点。如果有多个,按照从小到大输出。
分析: 不能构成一颗树的情况下考察连通块的个数,老生常谈的话题了。
能的情况下找到最深根结点。要利用结论,任选一个节点作为根结点,DFS树
最深的叶子节点是最深根结点全集的子集, 第二次选取最深根结点做起点DFS,
两次最深叶子结点集合并集就是最深根结点全集。
要点:一要知道这个结论,二,要写DFS将最深的叶子结点保存,可以定义一个
max_height变量。
简单
P1034
题目大意:给出1000条以内的通话记录A B和权值w,和阈值k,如果一个团伙人数
超过2人并且通话总权值超过k,令团伙里面的自身权值的最大值为头目,输出所有
满足条件的团伙的头目,和他们团伙里面的人数
分析:集合大小,集合边权总和,单个结点边权和。DFS可以做。
总的来说是一个判断一个图的连通分量的个数,用图的遍历解决,深度优先遍历
1.因为给的是字母,要用两个map把它们转换成数字,从1开始排列命名所有不同
的人的id,存储在两个map里面,一个字符串对应id,一个id对应字符串,方便
查找,正好顺便统计了总共的人数idNumber。
2.建立两个数组,weight和G,分别存储每条边的权值和每个结点的权值,因为这
两个题目中都要求得后判断。
3.用传递引用的方法深度优先dfs,这样传入的参数在dfs后还能保存想要求得
的值
4.遍历过一条边之后就把这条边的权值设为0( G[u][v] = G[v][u] = 0;)防止
出现回路遍历死循环(摘自柳神)
中等题
P1076
题目大意:给出每个用户关注的人的id,和转发最多的层数,求一个id发了条微博最多会有多少个人转发
分析:英文题读的让人头大。和前面不同,这是一个有向图,搞清楚弧的方向很重要。
带层数的广度优先,因为一个用户只能转发一次,所以用inq判断当前结点是否入队
过了,如果入队过了就不能重复入队(重复转发消息),inq 邻接表v 都可以使用int
只存储id,queue的数据类型必须为node,同时保存它的id和layer层数,控制不超过
L层~
(摘自柳神)
注意: 同一个结点在DFS和BFS生成树中高度是不一样的,这题的高度显然符合BFS
那种。树有很多运用,如并查集,采用路径压缩的并查集也类似一棵树,但是并查集
并不是一颗高度为2的树,只有查找操作的时候才会将除了根结点之外的结点全部接
到根结点上。
中等
小结
图的遍历非常重要,DFS和BFS函数一定要会写。
pat上图的遍历一共四道题,这四道题实质上都利用DFS或者BFS模版结合具体
情境解决实际问题,最基本的两个核心, pat题往往在这两个基础上加一些小问:
1, 图是否连通
2,图的连通块个数
除此之外还要掌握的内容:
1, 在DFS或者BFS遍历过程同时计算一些值,如整个连通图的权重和,或者
图中权重和最大的某个点。如1034
2,保存 DFS生成树的叶子结点
3,保存DFS生成树的最深叶子结点,如1021
3, 保存高度h<=h0的结点 如1076
4, 结点输入是字符串要会处理。如1034
5,用图判断树 如1021
思考:上述题目中哪些可以用并查集来做,如果可以,理由是什么?如果不行,也给出理由?
1013不行,因为去点去边在并查集中比较麻烦,而且还多次去点去边,并查集
不适合。
1021不行, 因为要比较节点的深度。并查集不适合,并查集可以统计集合数量。
1034不行, 因为要计算每个点的边权和,涉及到访问边。
1076不行,显然又涉及到树的深度问题,并查集不适合,路径压缩的时候直接破坏了原来的图关系。