|
本帖最后由 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;
- }
复制代码
|
评分
-
查看全部评分
|