[GESP202312 六级] 工作沟通(含视频)

视频讲解:GESP202312 六级 工作沟通-信息学奥赛GESP等级考试真题解析

一、原题

题目描述

某公司有 N 名员工,编号从 0 至 N−1。其中,除了 0 号员工是老板,其余每名员工都有一个直接领导。我们假设编号为 i 的员工的直接领导是 fi​。

该公司有严格的管理制度,每位员工只能受到本人或直接领导或间接领导的管理。具体来说,规定员工 x 可以管理员工 y,当且仅当 x=y,或 x=fy​,或 x 可以管理 fy​。特别地,0 号员工老板只能自我管理,无法由其他任何员工管理。

现在,有一些同事要开展合作,他们希望找到一位同事来主持这场合作,这位同事必须能够管理参与合作的所有同事。如果有多名满足这一条件的员工,他们希望找到编号最大的员工。你能帮帮他们吗?

输入格式

第一行一个整数 N,表示员工的数量。

第二行 N−1 个用空格隔开的正整数,依次为 f1​,f2​,...fN−1​。

第三行一个整数 Q,表示共有 Q 场合作需要安排。

接下来 Q 行,每行描述一场合作:开头是一个整数 m(2≤m≤N),表示参与本次合作的员工数量;接着是 m 个整数,依次表示参与本次合作的员工编号(保证编号合法且不重复)。

保证公司结构合法,即不存在任意一名员工,其本人是自己的直接或间接领导。

输出格式

输出 Q 行,每行一个整数,依次为每场合作的主持人选。

输入输出样例

输入 #1

复制代码
5
0 0 2 2
3
2 3 4
3 2 3 4
2 1 4

输出 #1

复制代码
2
2
0

输入 #2

复制代码
7
0 1 0 2 1 2
5
2 4 6
2 4 5
3 4 5 6
4 2 4 5 6
2 3 4

输出 #2

复制代码
2
1
1
1
0

说明/提示

样例解释 1

对于第一场合作,员工 3,4 有共同领导 2 ,可以主持合作。

对于第二场合作,员工 2 本人即可以管理所有参与者。

对于第三场合作,只有 0 号老板才能管理所有员工。

数据范围

对于 50% 的测试点,保证 N≤50。

对于所有测试点,保证 3≤N≤300,Q≤100。

二、做题思路

1)构造树

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
map<int,vector<int>>g;
int main(){
	//1)构造树
	int n;cin>>n;
	for(int i=1;i<=n-1;i++){
		int t;cin>>t;
		g[t].push_back(i);
	}
	return 0;
} 

2)深搜,记录每个结点的层数和祖宗结点

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	map<int,bool> storage;
	int deep;
}tree[310];//存储每个结点的高度 和 所有祖宗 
map<int,vector<int>>g;
map<int,vector<int>>d_storage;
void dfs(int x,int deep,map<int,bool> storage){
	//2.2)计算高度,存储到高度数组 
	tree[x].deep=deep;
	d_storage[deep].push_back(x);
	//2.3)加入当前结点 
	storage[x]=1;
	//2.4)记录之前传递的祖宗
	tree[x].storage=storage;
	//2.5)循环所有儿子 递归 
	for(auto it:g[x]){
		dfs(it,deep+1,storage);
	}
} 
int main(){
	//1)构造树
	int n;cin>>n;
	for(int i=1;i<=n-1;i++){
		int t;cin>>t;
		g[t].push_back(i);
	}
	//2)深搜,记录每个结点的层数和祖宗结点
	//2.1)从0开始 
	map<int,bool> temp_storage; 
	dfs(0,1,temp_storage);
	return 0;
} 

3)填充q次查询

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	map<int,bool> storage;
	int deep;
}tree[310];//存储每个结点的高度 和 所有祖宗 
map<int,vector<int>>g;
map<int,vector<int>>d_storage;
void dfs(int x,int deep,map<int,bool> storage){
	//...
} 
int main(){
	//1)构造树
	//... 
	//2)深搜,记录每个结点的层数和祖宗结点
	//2.1)从0开始 
	map<int,bool> temp_storage; 
	dfs(0,1,temp_storage);
	//3)填充q次查询
	//3.1)确定查询次数q 
	int q;cin>>q;
	for(int i=1;i<=q;i++){
		//3.2)填充m名员工 
		int m;cin>>m;
		int a[310];
		for(int j=1;j<=m;j++) cin>>a[j];
	}
	return 0;
} 

4)找出所有可能的父节点,找出最大

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	map<int,bool> storage;
	int deep;
}tree[310];//存储每个结点的高度 和 所有祖宗 
map<int,vector<int>>g;
map<int,vector<int>>d_storage;
void dfs(int x,int deep,map<int,bool> storage){
	//...
} 
int main(){
	//1)构造树
	//... 
	//2)深搜,记录每个结点的层数和祖宗结点
	//2.1)从0开始 
	map<int,bool> temp_storage; 
	dfs(0,1,temp_storage);
	//3)填充q次查询
	//3.1)确定查询次数q 
	int q;cin>>q;
	for(int i=1;i<=q;i++){
		//3.2)填充m名员工 
		int m;cin>>m;
		int a[310];
		for(int j=1;j<=m;j++) cin>>a[j];
		//4)找出所有可能的父节点,找出最大 
		//4.1)找最小高度 
		int minn=n;
		for(int j=1;j<=m;j++)
			minn=min(tree[a[j]].deep,minn);
		//4.2)从高度1 到 最小高度
		int maxx=0;
		for(int j=1;j<=minn;j++){
			//4.3)循环当前高度所有结点
			for(auto it:d_storage[j]){
				//4.4)判断m名员工是否都有该祖宗 
				bool flag=true;
				for(int h=1;h<=m;h++){
					if( tree[a[h]].storage[it]==0 ){
						flag=false;
						break;
					}
				}
				//4.5)找最大的节点
				if(flag) maxx=max(maxx,it);
			}
		}
		//4.6)输出结果 
		cout<<maxx<<"\n";
	}
	return 0;
} 

三、答案

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	map<int,bool> storage;
	int deep;
}tree[310];
map<int,vector<int>>g;
map<int,vector<int>>d_storage;
void dfs(int x,int deep,map<int,bool> storage){
	//2.2)计算高度,存储到高度数组 
	tree[x].deep=deep;
	d_storage[deep].push_back(x);
	//2.3)加入当前结点 
	storage[x]=1;
	//2.4)记录之前传递的祖宗
	tree[x].storage=storage;
	//2.5)循环所有儿子 递归 
	for(auto it:g[x]){
		dfs(it,deep+1,storage);
	}
} 
int main(){
	//1)构造树
	int n;cin>>n;
	for(int i=1;i<=n-1;i++){
		int t;cin>>t;
		g[t].push_back(i);
	}
	//2)深搜,记录每个结点的层数和祖宗结点
	//2.1)从0开始 
	map<int,bool> temp_storage; 
	dfs(0,1,temp_storage);
	//3)填充q次查询
	//3.1)确定查询次数q 
	int q;cin>>q;
	for(int i=1;i<=q;i++){
		//3.2)填充m名员工 
		int m;cin>>m;
		int a[310];
		for(int j=1;j<=m;j++) cin>>a[j];
		//4)找出所有可能的父节点,找出最大 
		//4.1)找最小高度 
		int minn=n;
		for(int j=1;j<=m;j++)
			minn=min(tree[a[j]].deep,minn);
		//4.2)从高度1 到 最小高度
		int maxx=0;
		for(int j=1;j<=minn;j++){
			//4.3)循环当前高度所有结点
			for(auto it:d_storage[j]){
				//4.4)判断m名员工是否都有该祖宗 
				bool flag=true;
				for(int h=1;h<=m;h++){
					if( tree[a[h]].storage[it]==0 ){
						flag=false;
						break;
					}
				}
				//4.5)找最大的节点
				if(flag) maxx=max(maxx,it);
			}
		}
		//4.6)输出结果 
		cout<<maxx<<"\n";
	}
	return 0;
} 
相关推荐
2601_9707038340 分钟前
除湿机原理研究报告:一台机器在物理上能走多远
大数据·数据结构·算法·数据库架构·推荐算法
♡すぎ♡1 小时前
SWE 的原理解析
算法·计算机图形学·swe
AiNightVision1 小时前
星光级 是什么?——星光级摄像机是什么?0.001Lux 照度门槛与选型真相
人工智能·算法·车载系统·自动驾驶·无人机·视频·智能硬件
若亦_1 小时前
排序>>选择排序
数据结构·算法·排序算法
重生之小比特1 小时前
【算法拾光】前缀和|一维前缀和 + 二维前缀和
数据结构·算法
释厄6231 小时前
矢量词汇向下不向上公理即词汇归位定律——肤浅即表面
java·人工智能·算法·去中心化·1024程序员节
海绵宝宝转agent1 小时前
Leetcode100+面经
java·笔记·学习·算法·leetcode·深度优先
Shaoshing2 小时前
LeetCode100 283.移动零
java·数据结构·算法·leetcode
海绵宝宝转agent2 小时前
LeetCode100个人题解+java面经总结
java·开发语言·笔记·学习·算法