树与图的遍历
树与图的深度优先遍历、广度优先遍历
树的构建(数组建立邻接表)
int n;
int h[N],e[M],ne[M];//h存某结点有多少个出度,e存下标对应的元素,ne存下一个下标
int idx;//下标
void add(int a,int b){//插入结点a指向的结点b。
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int main(){
cin>>n;
memset(h, -1, sizeof h); //初始化h数组 -1表示尾节点
for(int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
add(a,b),add(b,a);//无向图
}
return 0;
}
一、深度优先遍历
bool state[N];
void dfs(int u){
state[u]=true; // 标记一下,记录为已经被搜索过了,下面进行搜索过程
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(!state[j]) {
dfs(j);
}
}
}
树的重心
给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int const N=100010,M=2*N;
int n;
int h[N],e[M],ne[M];
int idx;
bool state[N];
int ans=N;//最终结果,是个最小值,故初始化最大值
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int u){
state[u]=true;
int res=0,sum=1;
//res存储某个子树结点数,sum以u为根的树的节点数(包括u故初始为1)
for(int i=h[u];i!=-1;i=ne[i]){
int j=e[i];
if(!state[j]){
int s=dfs(j);
res=max(res,s);//dfs能求出以u为根节点的一个子树的结点个数
sum+=s;
}
}
res=max(n-sum,res);//和另一半的结点个数比较
ans=min(res,ans);
return sum;
}
int main(){
cin>>n;
memset(h, -1, sizeof h); //初始化h数组 -1表示尾节点
for(int i=0;i<n-1;i++){
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
dfs(1);
cout<<ans<<endl;
return 0;
}
二、广度优先遍历
void bfs(){
queue<int> q;
memset(d,-1,sizeof d);
d[1]=0;
q.push(1);
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(d[j]==-1){
d[j]=d[t]+1;
q.push(j);
}
}
}
}
图中点的层次
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环。所有边的长度都是 1,点的编号为 1∼n。请你求出 1 号点到 n 号点的最短距离,如果从 1 号点无法走到 n 号点,输出 −1。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=100010;
int n,m;
int h[N],e[N],ne[N],idx;
int d[N],q[N];
void add(int a,int b){
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
int bfs(){
queue<int> q;
memset(d,-1,sizeof d);
d[1]=0;
q.push(1);
while(!q.empty()){
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(d[j]==-1){
d[j]=d[t]+1;
q.push(j);
}
}
}
return d[n];
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
add(a,b);
}
cout<<bfs()<<endl;
return 0;
}