树与图的遍历

树与图的关系:图可以分为有向图和无向图,而树是一种特殊的图,即无环连通图,所以树和图的遍历方式可以作统一讨论。在遍历之前,要先进行储存。

储存模板较为简单,如下:

memset(h,-1,sizeof h);
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}

与拉链法相似,h数组可以理解为主链,e、ne、idx与单链插入中所用到的作用相同。此函数作用可以理解为将b接在以a所在主链位置的支链上,令a指向b。在进行无向图储存时,只需要add(a,b);add(b,a),使a与b双向指向。

树与图的遍历:

1.深度优先遍历:

主要模板

bool st[N];
void dfs(int u)
{
	st[u]=true;
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(!st[j]) dfs(j);
	}
}

st用于记录当前节点的访问状态,循环递归访问每一个节点并记录、处理,每次都从一个节点访问到没有下位节点为止,以达到深度优先遍历。

应用例题:

 在这题中,需要在遍历每个节点的时候记录删掉该点后剩余连通块中点数的最大值:

int dfs(int u)
{
	st[u]=ture;
	int sum=1,res=0;
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int j=e[i];
		if(!st[j])
		{
			int s=dfs(j);
			res=max(res,s);
			sum+=s;
		}
	}
	res=max(res,n-sum);
	ans=min(ans,res);
	return sum;
}

-----------------------------------------------------------------------------------------------------------------------------------------------------

2.宽度优先遍历

应用模板:

int bfs()
{
	int hh=0,tt=0;
	q[0]=1;
	memset(d,-1,sizeof d);
	d[1]=0;
	while(hh<=tt)
	{
		int t=q[hh++];
		for(int i=h[t];i!=-1;i=ne[i])
		{
			int j=e[i];
			if(d[j]==-1)
			{
				d[j]=d[t]+1;
				q[++tt]=j;
			}
		}
	}
	return d[n];
}

其中d数组表示每个点与起点的距离,该函数最终会返回1到n的距离,以宽度优先搜索的方式从1开始一层一层的判断。

对于宽度优先搜索在无环有向图上的应用,可以进行拓扑排序以得到图中的拓扑数:

bool topsort()
{
	int hh=0,tt=-1;
	for(int i=1;i<=n;i++)
		if(!d[i])
			q[++tt]=i;
	
	while(hh<=tt)
	{
		int t=q[hh++];
		for(int i=h[t];i!=-1;i=ne[i])
		{
			int j=e[i];
			d[j]--;
			if(d[j]==0) q[++tt]=j;
		}
	}
	return tt==n-1;
}

树与图的遍历就是对深度优先遍历和宽度优先遍历的应用,主要还是根据题意对模板的修改与活用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值