|树的静态写法、寻找树的根节点、dfs寻找最深的叶子节点|L2-031 深入虎穴 (25)

link
在这里插入图片描述

至于怎么找根节点
由于题目直接给了点和点点的关系
所以我们可以得出哪个是根节点
即,没有爸爸的点是根节点(和并查集操作最后的判断0类似)

我们要找特殊的点
在树里
特殊的点有孩子节点
所以我们就去找孩子节点
找到了孩子节点,我们可要好好的操作一番啊
不要直接逃走return;
而是记录下根节点到它的路径长度(高度),与最大高度比较

//输入首先在一行中给出正整数 N( < 10​5​​),是门的数量。
//最后 N 行,第 i 行(1≤i≤N)按以下格式描述编号为 i 的那扇门背后能通向的门

//K D[1] D[2] ... D[K]
/*
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
*/
//--------------
//在一行中输出距离入口最远的那扇门的编号。
//12

//1.查找入口//又没被当作儿子
//2.通过dfs遍历查找最深子节点
//10^5--->邻接表---静态写法
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

const int N = 100010;
int n;
vector<int> G[N];
int isRoot[N] = { 0 };//详见并查集求根节点
int root = 0;
//int vis[N] = {0};//
int max_d = 0,max_v=1;

void dfs(int v,int depth) {
	//vis[v] = 1;
	/*if (G[v].size() == 0)return;//访问到了孩子节点,到头了
	else {
		if (depth > max_d) {
			max_d = depth;
			max_v = v;
		}
	}*/
	/*
	if (!G[v].size()) {
		if (depth > max_d) {
			max_d = depth;
			max_v = v;
		}
		return;
	}*/

	//找到孩子节点
	//我们应该怎么办?
	//我们不应该直接return;,不做操作
	//我们应该求它的层数啊,毕竟它是根节点到它的最长路径(虽然可能不是最长路径,那么比一下就知道了)
	if (G[v].size() == 0) {
		if (depth > max_d) {
			max_d = depth;
			max_v = v;
		}else {//抱歉我没有比max_d长
			return;
		}
	}
		for (int i = 0; i < G[v].size(); i++) {
			//if (vis[G[v][i]] == 0)
				dfs(G[v][i],depth + 1);
		}
	
	//}

}

int main() {
	cin >> n;//编号1~n
	for (int i = 1; i <= n; i++) {
		int k;
		cin >> k;
		for (int j = 0; j < k; j++) {
			int tmp;
			cin >> tmp;
			isRoot[tmp] =1;//有爸爸的就不是root了
			G[i].push_back(tmp);
		}
	}
	for (int i = 1; i <= n; i++) {
		if (isRoot[i] == 0) {
			root = i;
			break;
		}
	}
	//cout << "-------------"<<endl;
	//cout << root << endl;
	dfs(root,0);//第一层
	cout << max_v;
	return 0;
}



//输入首先在一行中给出正整数 N( < 10​5​​),是门的数量。
//最后 N 行,第 i 行(1≤i≤N)按以下格式描述编号为 i 的那扇门背后能通向的门

//K D[1] D[2] ... D[K]
/*
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
*/
//--------------
//在一行中输出距离入口最远的那扇门的编号。
//12

//1.查找入口//又没被当作儿子
//2.通过dfs遍历查找最深子节点
//10^5--->邻接表---静态写法
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;

const int N = 100010;
int n;
vector<int> G[N];
int isRoot[N] = { 0 };//详见并查集求根节点
int root = 0;
//int vis[N] = {0};//
int max_d = 0,max_v=1;

void dfs(int v,int depth) {
	//vis[v] = 1;
	/*if (G[v].size() == 0)return;//访问到了孩子节点,到头了
	else {
		if (depth > max_d) {
			max_d = depth;
			max_v = v;
		}
	}*/
	if (!G[v].size()) {
		if (depth > max_d) {
			max_d = depth;
			max_v = v;
		}
		return;
	}
		for (int i = 0; i < G[v].size(); i++) {
			//if (vis[G[v][i]] == 0)
				dfs(G[v][i],depth + 1);
		}
	
	//}

}

int main() {
	cin >> n;//编号1~n
	for (int i = 1; i <= n; i++) {
		int k;
		cin >> k;
		for (int j = 0; j < k; j++) {
			int tmp;
			cin >> tmp;
			isRoot[tmp] =1;//有爸爸的就不是root了
			G[i].push_back(tmp);
		}
	}
	for (int i = 1; i <= n; i++) {
		if (isRoot[i] == 0) {
			root = i;
			break;
		}
	}
	cout << "-------------"<<endl;
	cout << root << endl;
	dfs(root,0);//第一层
	cout << max_v;
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值