图的遍历(洛谷)

  • p2661 信息传递

这道题实际上就是求图的最小环,这里用并查集的方法实现。

#include <cstdio>
#include <algorithm>
using namespace std ;
const int N = 2e5 + 5 ; 
int s[N] , h[N] ;
int ans = N ; 
int find(int x){
	if (x != s[x]){
		int t = s[x] ;	//记录父节点 
		s[x] = find(s[x]) ;	//更新为祖先节点 
		h[x] += h[t] ; 
		//h[x]是x相对于父节点的长度,h[t]是x的父节点相对于祖先节点的长度,合起来就是x相对于祖先节点的长度,且x已经更新为祖先节点了 
	}
	return s[x] ; 
}
void built(int x , int y){
	int a = find(x) ;
	int b = find(y) ; 
	if (a != b){
		s[a] = b ;
		h[x] = h[y] + 1 ;
	}else{
		ans = min(ans,h[x]+h[y]+1) ; //祖先节点相同则可以成环(环的长度为两个节点到祖先节点的长度+1) 
	}
}
int main(){
	int n ; 
	scanf ("%d",&n) ;
	for (int i = 1 ; i <= n ; ++ i){
		s[i] = i ; 
		h[i] = 0 ; 
	} 
	for (int i = 1 ; i <= n ; ++ i){
		int x ; 
		scanf ("%d",&x) ;
		built(i,x) ; 
	}
	printf ("%d\n",ans) ; 
	return 0 ; 
}
  • p1330 封锁阳光

题意是每个点要分隔开但是取走的点不能相邻,转化为染色就是相邻的点不能为同种颜色。
做法:遍历未染色的点,将未染色的点染为黑色,相邻的点染为白色,依次类推,要注意每次dfs是当前的联通图,取断点要去当前的最小值,所以在开始遍历那里之前,颜色数量要清0。

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std ; 
const int N = 1e4 + 5 ; 
int n , m ; 
int vis[N] , color[2] ; 
vector<int> r[N] ; 
int ans ; 
int dfs(int i){
	for (int j = 0 ; j < r[i].size() ; ++ j){
		int t = r[i][j] ; 
		if (vis[t] == -1){
			vis[t] = (vis[i]+1)%2 ; 
			color[vis[t]] ++ ;	
			dfs(t) ; 
		}
		else{
			if (vis[i] == vis[t]){	//新的颜色和旧的颜色相同(冲突)
				printf ("Impossible\n") ;
				exit(0) ; //退出程序  
			}
		}
	}
	return min(color[0],color[1]+1) ; 
}
int main(){
	scanf ("%d%d",&n,&m) ;
	memset(vis,-1,sizeof(vis)) ; 
	while(m--){	//建图 
		int v , u ; 
		scanf ("%d%d",&v,&u) ; 
		r[v].push_back(u) ; 
		r[u].push_back(v) ; 
	}
	for (int i = 1 ; i <= n ; ++ i){
		if (r[i].size() == 0)	continue ;  //为单独的点不用搜索
		color[0] = 0 , color[1] = 0 ;	//注意清0,因为每次要返回当前连通图染色数最少的点 
		if (vis[i] == -1){	//未上色
			vis[i] = 1 ; 
			ans += dfs(i) ; 
		}
	}
	printf ("%d\n",ans) ;
	return 0 ; 
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
洛谷B3642是关于二叉树遍历的题目。具体要求如下: 1. 对给定的二叉树进行先序、中序、后序和层次遍历,并输出结点的遍历序列。 2. 求二叉树的深度、结点数目和叶结点数目。 3. 可选做的题目是将二叉树的每个结点的左右子树交换位置。 根据引用的经验,可以采用深度优先搜索(DFS)的方式来遍历二叉树,通过先序遍历的顺序来求各个子树的结点。首先,在DFS的函数中,找到后序遍历的最后一个结点作为根结点,并根据根结点将字符串s1和s2划分为左子树和右子树的字符串。然后,递归地对左子树和右子树进行DFS。最后,输出根结点的值。这样就可以得到先序遍历的结果。 对于中序遍历和后序遍历的结果,可以通过相应的位置关系计算得到。例如,在DFS的过程中,可以在输出根结点之前输出左子树的结点,然后再输出右子树的结点,即可得到中序遍历的结果。同样地,在输出根结点之后,依次输出左子树和右子树的结点,即可得到后序遍历的结果。 至于层次遍历,可以使用队列的方式来实现。从根结点开始,依次将每个结点的左子树和右子树加入队列,并在出队的时候输出结点的值,直到队列为空。 综上所述,可以按照如下步骤来解答洛谷B3642题目: 1. 设计一个DFS函数,用于遍历二叉树并输出先序遍历的结果。 2. 在DFS函数中,根据后序遍历的特点找到根结点,并将s1和s2划分为左子树和右子树的字符串。 3. 在DFS函数中,递归地对左子树和右子树进行DFS,并在输出根结点之前或之后输出结点的值,从而得到中序和后序遍历的结果。 4. 设计一个层次遍历函数,使用队列的方式按层遍历二叉树,并输出结点的值,直到队列为空。 5. 根据题目要求,计算二叉树的深度、结点数目和叶结点数目。 请注意,以上步骤是一种可能的解答方案,你可以根据自己的理解和方法进行解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [4/9学习日记](https://blog.csdn.net/qq_74042166/article/details/130048431)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [二叉树_二叉树遍历_](https://download.csdn.net/download/weixin_42683394/27951460)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值