|
本帖最后由 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
输出样例
样例解释
第一次询问: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
注:该题非原创,改编于:https://www.luogu.com.cn/problem/P3379
答案与解析
[/hide]
最佳战士排行榜
| 第一名 | 第二名 | 第三名
| 名字 | 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. 因为额度原因,部分鱼油可能下一天才能奖励。
下一关:待更新
创作不易,如果你喜欢,别忘了评分、顶
本关满意度调查
试逝 #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[MaximumNode << 1];
struct node nodes[MaximumNode];
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[edge].to;
struct node* next_node = nodes + next;
unsigned int next_edge = edges[edge].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[current->heir].size < nodes[next].size){
current->heir = next;
}
edges[edge].next = current->edge;
current->edge = edge;
}
edge = next_edge;
}
}
void generate(unsigned int target){
struct node* current = nodes + target;
if(current->heir != 0){
nodes[current->heir].leader = current->leader;
generate(current->heir);
}
unsigned int edge = current->edge;
while(edge != (unsigned int)-1){
if(edges[edge].to != current->heir){
nodes[edges[edge].to].leader = edges[edge].to;
generate(edges[edge].to);
}
edge = edges[edge].next;
}
}
void build_tree(unsigned int root){
nodes[root].depth = 0;
nodes[root].visited = true;
nodes[root].parent = 0;
dfs(root);
}
void generate_tree(unsigned int root){
nodes[root].leader = root;
generate(root);
}
unsigned int lca(unsigned int x, unsigned int y){
while(nodes[x].leader != nodes[y].leader){
if(nodes[nodes[x].leader].depth < nodes[nodes[y].leader].depth){
x ^= y;
y ^= x;
x ^= y;
}
x = nodes[nodes[x].leader].parent;
}
return nodes[x].depth > nodes[y].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[i].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[current_edge].to = y;
edges[current_edge].next = nodes[x].edge;
nodes[x].edge = current_edge++;
edges[current_edge].to = x;
edges[current_edge].next = nodes[y].edge;
nodes[y].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;
}
|
评分
-
查看全部评分
|