图的基础概念
度数:出边+入边的条数
有向边:有箭头
图的存储方式
//邻接表 List<int []> list[N] list<x>//存放x的所有出点的信息 list[i][j]={first,second}//其中first表示从i出发的某个出点的编号(这个出点是i的第j个出点),second表示边权 list[1]={{2,0},{3,0}}
//邻接矩阵 d[i][j]//表示从i到j的边的距离(一般情况下为最短距离)如果不存在边的距离为-1.例如右图中: d[1,2]=0 d[6,3]=7 d[4,3]=-1
DFS遍历图
DFS是深度优先搜索,“一条路走到黑,走过路不会再走”
对于上述图像中的图,我们可以画出它从1开始的DFS轨迹。注意DFS不是唯一的,因为每次的顺序不一样,只要走完就可以了
代码
DFS一般用递归实现
boolean<N>v;//v[i]=true说明i点已经走过了 void dfs(int x){ v[x]=true;//打上标记 for(int y:list[x]){ if(v[y])continue;//如果已经打上标记跳过 dfs(y); } }
BFS遍历图
BFS是宽度优先搜索,核心思想是“一层一层往外走,每个点只走一次”,对于下面这个图我们可以画出它的从1开始的BFS轨迹
BFS通常用于求边权相等情况下的最短距离。
代码
BFS一般用队列来实现
boolean<N> vis; queue<int> q;//q表示待扩展的点队列 while(q.size()>0)//只要队列不为空 { int x=q.pop(); if(v[x])continue; v[x]=true; for(int y:list[x]) q.push(y); }
例题展示
小明在游戏中参加了一个帮派,这一天它突然想知道自己在帮派中是什么地位,但是半拍的查询系统突然坏了,目前只能直到每个人的附属关系,请问你能帮他重建关系网并找出它的地位吗?
给定一个正整数n,代表该帮派的总人数,并且小明的序号是m,给出这n个人中每个人的附属关系,确保给出的关系网为一棵树,帮派地位的定义是按照自己手下有多少帮众决定的,注意手下的手下也算自己的手下。如果手下的帮众相同则按照序号较小的在前面,你能帮助小明找到自己的帮派地位吗?
输入格式
第一行,两个正整数n(1<=n<=10^5)和m(1<=m<=n),代表该帮派的总人数以及小明的序号。
接下来n-1行,每行两个正整数,格式如下:
l,r代表序列为l的人附属与序号为r的人。
输出格式
一行,包含1个正整数,输出按手下人数多少排序后小明的排名。
(答案下期见)