树
1.树上最短路
https://www.nowcoder.com/questionTerminal/3ead0c7164344b7a873a5916bf05de33?answerType=1&f=discussion
在向上找公共祖先的过程中,记录路径,直到找到同一个公共祖先
#include <iostream> using namespace std; int main() { int n; cin >> n; int a, b; while (n--) { cin >> a >> b; int res = 0; while (a != b) { if (a > b) { a = a / 2; res++; } if (a < b) { b = b / 2; res++; } } cout << res << endl; } } // 64 位输出请用 printf("%lld")
2.无穷大满二叉树,其根节点一层一层的从左向右依次编号,根节点编号为1,求a b两个节点的最近公共祖先编号
#include <iostream> using namespace std; int main() { int n; cin >> n; long long a, b; // ✅ 用 long long 防止大数溢出 while (n--) { cin >> a >> b; while (a != b) { if (a > b) { a /= 2; } else { b /= 2; } } cout << a << endl; } return 0; }
3.小红的树
https://www.nowcoder.com/practice/66ab364d3fba487eb39bd3460fd484c0?tpId=308&tqId=1747923&sourceUrl=/exam/oj&channelPut=wcsdn&fromPut=wcsdn
知识点:
1.邻接表表示树
代入执行流程(从根节点 1 开始)
我们从根节点 1 开始调用:
第一步:dfs(1, s, dp, G)
x = 1,对应颜色字符是s[0] = 'W'→ 不增加 count;count = 0;- 子节点是
2和4,依次递归调用:
子节点 1.1:dfs(2, s, dp, G)
x = 2,对应s[1] = 'R'→count = 1- 子节点是
3,继续递归:
子节点 1.1.1:dfs(3, s, dp, G)
-
x = 3,对应s[2] = 'W'→count = 0 -
没有子节点 → 直接返回
dp[3] = 0 -
返回后,
count += dfs(3)→count = 1 + 0 = 1 -
返回
dp[2] = 1
子节点 1.2:dfs(4, s, dp, G)
x = 4,对应s[3] = 'R'→count = 1- 子节点是
5,继续递归:
子节点 1.2.1:dfs(5, s, dp, G)
-
x = 5,对应s[4] = 'R'→count = 1 -
没有子节点 → 返回
dp[5] = 1 -
返回后,
count += dfs(5)→count = 1 + 1 = 2 -
返回
dp[4] = 2
回到根节点 1:
count += dfs(2)→count += 1→count = 0 + 1 = 1count += dfs(4)→count += 2→count = 1 + 2 = 3- 返回
dp[1] = 3
#include <bits/stdc++.h> using namespace std; int dfs(int x, vector<vector<int>> &G, vector<int>&dp, string &str){ int count = 0; if (str[x-1] == 'R') count++; for (int i = 0; i <G[x].size(); i++){ count += dfs(G[x][i], G , dp , str); } return dp[x] = count; } int main(){ int n; cin >> n; vector<vector<int>> G(n+1); for (int i=2; i <= n; i++){ int temp; cin >> temp; G[temp].push_back(i); } string str; cin >> str; vector<int> dp(n+1); dfs(1, G, dp, str); int q; cin >> q; while(q--){ int x; cin >> x; cout << dp[x] << endl; } }
浙公网安备 33010602011771号