【C++板块提升计划】梦想护卫舰 第25关 最近公共祖先
本帖最后由 zhangjinxuan 于 2023-2-19 15:21 编辑上一关:性能测试
梦想护卫舰 第25关 最近公共祖先
梦想护卫舰终于继续出发
这时,高山发现,船上有很多人都有亲戚关系,现在给定 N - 1 对人的关系,请求出任意两个人的最年轻的公共祖先是谁
输入格式
第一行包含三个正整数 N,M,S,分别表示人的个数、询问的个数和最老祖先的序号。
接下来 N-1 行每行包含两个正整数 ,x,y,表示第 x 人和第 y 人存在亲戚关系(我们保证能够造成一棵树)。
接下来 M 行每行包含两个正整数 a,b,表示询问第 a 人和第 b 人的最年轻的公共祖先。
输出格式
输出包含 M 行,每行包含一个正整数,依次为每一个询问的结果。
输入样例
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出样例
4
4
1
4
4
样例解释
https://cdn.luogu.com.cn/upload/pic/2282.png
第一次询问:2,4 的最近公共祖先,故为 4
第二次询问:3,2的最近公共祖先,故为 4
第三次询问:3,5 的最近公共祖先,故为 1
第四次询问:1,2 的最近公共祖先,故为 4
第五次询问:4,5 的最近公共祖先,故为 4
故输出依次为 4,4,1,4,4。
数据范围
对于 70% 的数据,保证 1 <= n, m <= 10000
对于 100% 的数据,保证 1 <= n, m <= 500000,1 <= x, y, a, b <= n, 但可能存在 a = b
static/image/hrline/1.gif
注:该题非原创,改编于:https://www.luogu.com.cn/problem/P3379
static/image/hrline/1.gif
答案与解析
**** Hidden Message *****
最佳战士排行榜
|第一名|第二名|第三名
名字|dolly_yos2|ExiaGN001|
链接|戳我|戳我|
语言|C++|C++|
代码得分|100|70|
奖励|5鱼币5荣誉+“最佳答案”|3鱼币3荣誉|2鱼币2荣誉
我们一起来 Hack
Hack 规则
1. Hack 经证实均有奖励,你在 Hack 时得提供完整证据、证明;
2. 在本关,仅支持标程 Hack,细节问题奖励 2~5 鱼币,重点问题奖励 5~10 鱼币
3. 奖励上限为 3 次
名字|等待着Hack大佬~
Hack 类型|
是否证实|
链接|
奖励|
答题/奖励规则
1. 不能抄题解,否则无奖励,可能还会扣分;
2. 当您遇到问题时,您可以回贴提问,我会为您解答
3. 提供完整能得分的题解,均有奖励。
4. 因为额度原因,部分鱼油可能下一天才能奖励。
static/image/hrline/1.gif
下一关:待更新
创作不易,如果你喜欢,别忘了评分、顶{:10_281:}
本关满意度调查 本帖最后由 ExiaGN001 于 2023-2-19 11:24 编辑
暴力做会TLE的
暴力代码(吸氧70pts)
#include<bits/stdc++.h>
//#pragma GCC optimize(2)
using namespace std;
int r;
vector<int> e2;
int e;
int ans;int n,m,s;
void dfs2(int num,int type)
{
if(type==1&&r==1)
{
ans=num;
return ;
}
if(type==0)
{
r=1;
if(num!=s)
dfs2(e,type);
}
if(type==1)
{
if(num!=s)
dfs2(e,type);
}
}
void dfs(int num,int f)
{
e=f;
int v;
for(int i=0;i<e2.size();i++)
{
v=e2;
if(v!=f)
dfs(v,num);
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>s;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
e2.push_back(x);
e2.push_back(y);
}
dfs(s,0);//重新建树
while(m--)
{
int x,y;
cin>>x>>y;
if(y==x){cout<<x<<"\n";continue;}
memset(r,0,sizeof(r));
dfs2(x,0);
dfs2(y,1);
cout<<ans<<"\n";
}
}
ExiaGN001 发表于 2023-2-19 11:23
暴力做会TLE的
暴力代码(吸氧70pts)
满分才会有最佳答案哦{:10_282:}
写个倍增吧,也费不了多少{:10_256:} 这不就是模板题——倍增lca 吗 666 试逝#include <stdio.h>
#include <stdbool.h>
struct edge{
unsigned int to;
unsigned int next;
};
struct node{
unsigned int edge;
unsigned int parent;
unsigned int heir;
unsigned int size;
unsigned int depth;
unsigned int leader;
bool visited;
};
enum{ MaximumNode = 500001 };
struct edge edges;
struct node nodes;
void dfs(unsigned int target){
struct node* current = nodes + target;
current->size = 1;
current->heir = 0;
unsigned int edge = current->edge;
current->edge = -1;
while(edge != (unsigned int)-1){
unsigned int next = edges.to;
struct node* next_node = nodes + next;
unsigned int next_edge = edges.next;
if(!next_node->visited){
next_node->depth = current->depth + 1;
next_node->visited = true;
next_node->parent = target;
dfs(next);
current->size += next_node->size;
if(current->heir == 0 || nodes.size < nodes.size){
current->heir = next;
}
edges.next = current->edge;
current->edge = edge;
}
edge = next_edge;
}
}
void generate(unsigned int target){
struct node* current = nodes + target;
if(current->heir != 0){
nodes.leader = current->leader;
generate(current->heir);
}
unsigned int edge = current->edge;
while(edge != (unsigned int)-1){
if(edges.to != current->heir){
nodes.to].leader = edges.to;
generate(edges.to);
}
edge = edges.next;
}
}
void build_tree(unsigned int root){
nodes.depth = 0;
nodes.visited = true;
nodes.parent = 0;
dfs(root);
}
void generate_tree(unsigned int root){
nodes.leader = root;
generate(root);
}
unsigned int lca(unsigned int x, unsigned int y){
while(nodes.leader != nodes.leader){
if(nodes.leader].depth < nodes.leader].depth){
x ^= y;
y ^= x;
x ^= y;
}
x = nodes.leader].parent;
}
return nodes.depth > nodes.depth ? y : x;
}
int main(){
unsigned int n, s, m;
scanf("%u%u%u", &n, &m, &s);
for(unsigned int i = 1; i <= n; i++) nodes.edge = -1;
unsigned int x, y;
for(unsigned int i = 1, current_edge = 0; i < n; i++, current_edge++){
scanf("%u%u", &x, &y);
edges.to = y;
edges.next = nodes.edge;
nodes.edge = current_edge++;
edges.to = x;
edges.next = nodes.edge;
nodes.edge = current_edge;
}
build_tree(s);
generate_tree(s);
for(unsigned int i = 0; i < m; i++){
scanf("%u%u", &x, &y);
printf("%u\n", lca(x, y));
}
return 0;
} dolly_yos2 发表于 2023-2-19 13:41
试逝
可以,通过{:10_256:} zhangjinxuan 发表于 2023-2-19 14:13
可以,通过
所以我们既不需要暴力也不需要倍增(笑) dolly_yos2 发表于 2023-2-19 14:34
所以我们既不需要暴力也不需要倍增(笑)
我*,这是啥{:10_277:} 1 {:10_266:} 我和zhangjinxuan可能有亲戚关系(姓:张) hveagle 发表于 2023-3-7 19:10
我和zhangjinxuan可能有亲戚关系(姓:张)
我们不是都有一个祖先么,猿猴,呜呜啊啊{:10_302:}
或者同一个细胞分裂成的{:10_256:}
但要说最近的公共祖先,嗯,不好说 zhangjinxuan 发表于 2023-3-7 19:12
我们不是都有一个祖先么,猿猴,呜呜啊啊
或者同一个细胞分裂成的
最近是张居正{:10_256:} hveagle 发表于 2023-3-7 19:13
最近是张居正
啊{:10_277:}额{:10_257:}哈{:10_256:}
你把我帖子所有选项都给选了{:10_282:} zhangjinxuan 发表于 2023-3-7 19:14
啊额哈
你把我帖子所有选项都给选了
{:10_295:}
页:
[1]