蓝桥杯 团建

团建

问题描述

小蓝正在和朋友们团建,有一个游戏项目需要两人合作,两个人分别拿到一棵大小为 nm 的树,树上的每个结点上有一个正整数权值。两个人需要从各自树的根结点 1 出发,走向某个叶结点。从根到这个叶结点的路径上经过的所有结点上的权值构成了一个正整数序列。两人的序列的最长公共前缀即为他们的得分。请给出两棵树,请计算两个人最多的得分是多少。

输入格式

  • 第一行包含两个正整数 n, m,用一个空格分隔。
  • 第二行包含 n 个正整数 c_1, c_2, ..., c_n,相邻整数之间使用一个空格分隔,其中 c_i 表示第一棵树结点 i 上的权值。
  • 第三行包含 m 个正整数 d_1, d_2, ..., d_m,相邻整数之间使用一个空格分隔,其中 d_i 表示第二棵树结点 i 上的权值。
  • 接下来 n-1 行,每行包含两个正整数 u_i, v_i,表示第一棵树中包含一条 u_iv_i 之间的边。
  • 接下来 m-1 行,每行包含两个正整数 p_i, q_i,表示第二棵树中包含一条 p_iq_i 之间的边。

输出格式

输出一行,包含一个整数,表示答案,即两人最多的得分。

样例输入 1

in 复制代码
2 2
10 20
10 30
1 2
2 1

样例输出 1

out 复制代码
1

解释

在这个样例中,两个序列分别为 [10, 20][10, 30]。它们的最长公共前缀为 1

样例输入 2

in 复制代码
5 4
10 20 30 40 50
10 40 20 30
1 2
1 3
2 4
3 5
1 2
1 3
3 4

样例输出 2

out 复制代码
2

解释

在这个样例中,两个序列分别为 [10, 20, 40][10, 20, 30]。它们的最长公共前缀为 [10, 20],长度为 2

评测用例规模与约定

对于 20% 的评测用例,1 ≤ n, m ≤ 500

对于所有评测用例,1 ≤ n, m ≤ 2 × 10^51 ≤ c_i, d_i ≤ 10^81 ≤ u_i, v_i ≤ n1 ≤ p_i, q_i ≤ m

对于任意结点,其儿子结点的权重互不相同。

c++代码

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

class tree {
public:
    int val;
    unordered_map<int, tree*> sons;
    tree(int val) {
        this->val = val;
    }
};

int n, m, a, b, ans = 0;
vector<tree*> a_tree;
vector<tree*> b_tree;

void dfs(tree* p, tree* m, int index) {
    for (auto z : p->sons) {
        tree* middle = z.second;
        if (m->sons.find(middle->val) != m->sons.end()) dfs(middle, m->sons[middle->val], index + 1);
    }
    ans = max(ans, index);
}

int main() {
    cin >> n >> m;
    a_tree = vector<tree*>(n), b_tree = vector<tree*>(m);
    for (int i = 0; i < n; i++) {
        cin >> a;
        a_tree[i] = new tree(a);
    }
    for (int i = 0; i < m; i++) {
        cin >> b;
        b_tree[i] = new tree(b);
    }
    for (int i = 0; i < n - 1; i++) {
        cin >> a >> b;
        if (a > b) swap(a, b);
        a_tree[a - 1]->sons[a_tree[b - 1]->val] = a_tree[b - 1];
    }
    for (int i = 0; i < m - 1; i++) {
        cin >> a >> b;
        if (a > b) swap(a, b);
        b_tree[a - 1]->sons[b_tree[b - 1]->val] = b_tree[b - 1];
    }
    if (a_tree[0]->val != b_tree[0]->val) {
        cout << 0 << endl;
        return 0;
    }
    dfs(a_tree[0], b_tree[0], 1);
    cout << ans << endl;
    return 0;
}//by wqs

题目解析

首先你把两棵树建立出来,然后就是同时深度遍历这两棵树,也就是同时从根节点出发,同时前往下一层,当然要求下一层的节点值相等。直到不能相等为止,这个时候的递归深度你记录下来,和ans去比较就行了。

代码实现

结构体定义
cpp 复制代码
class tree {
public:
    int val;
    unordered_map<int, tree*> sons;//方便查找
    tree(int val) {
        this->val = val;
    }
};
建树
cpp 复制代码
for (int i = 0; i < n - 1; i++) {
    cin >> a >> b;
    if (a > b) swap(a, b);
    a_tree[a - 1]->sons[a_tree[b - 1]->val] = a_tree[b - 1];
}
for (int i = 0; i < m - 1; i++) {
    cin >> a >> b;
    if (a > b) swap(a, b);
    b_tree[a - 1]->sons[b_tree[b - 1]->val] = b_tree[b - 1];
}
dfs深度搜索
cpp 复制代码
void dfs(tree* p, tree* m, int index) {
    for (auto z : p->sons) {
        tree* middle = z.second;
        if (m->sons.find(middle->val) != m->sons.end()) dfs(middle, m->sons[middle->val], index + 1);
    }
    ans = max(ans, index);
}

ans就是我们的答案

相关推荐
wuyk55512 分钟前
21.计数排序:不用比较的“空间换时间”排序算法
python·算法·排序算法
stolentime23 分钟前
CSP-J2026第一轮试题(附答案解析、markdown源码)
c++·csp
船厂电气自动化ai大模型24 分钟前
AI大模型与数学|第81天 课程:正交向量、正交基、格拉姆‑施密特(Gram‑Schmidt)正交化
开发语言·数据结构·人工智能·线性代数·机器学习
Rabitebla25 分钟前
【Linux系统编程】 指令(二):一条路径是怎么定位到文件的
linux·c++·笔记·学习·算法
phltxy28 分钟前
C语言结构体
c语言
库玛西34 分钟前
数据结构与算法之美:树、森林与二叉树全解析
c语言·数据结构·笔记·考研·算法·学习方法
木井巳35 分钟前
【记忆化搜索】最长递增子序列
java·算法·leetcode·深度优先·剪枝·推荐算法
2601_9555181836 分钟前
如何学好C语言:从入门到精通,掌握编程基石
c语言·指针·项目实战·调试技巧·编程基础
东方护航数据恢复(深圳)39 分钟前
本地小算力设备数据恢复经典案例实操全解_东方护航数据恢复深圳店
大数据·服务器·算法·ai·gpu算力
Omics Pro1 小时前
上海AI Lab孙思琦×高张阳:虚拟细胞代码库智能体
数据库·人工智能·算法·机器学习·自然语言处理