設計模式之訪問者模式(Visitor)
阿新 • • 發佈:2021-07-31
#include <bits/stdc++.h> using namespace std; int n, x, y, u, v; const int N = 110; //樹的結構體+儲存陣列 struct Node { int id; // 當前結點ID int father; // 爸爸 int left; // 左結點ID int right; // 右結點ID int depth; // 深度,不用再次dfs去探測 } t[N]; //記錄邊的關係 typedef pair<int, int> PII; PII a[N]; //是不是使用過 int st[N]; //用來計某一層的結點個數 int bucket[N]; //通過遞迴構建二叉樹 void dfs(int u) { //u是老大,找出它的左兒子和右兒子 for (int i = 1; i < n; i++) {//遍歷所有關係 if (a[i].first == u && !st[a[i].second]) { //標識已使用 st[a[i].second] = 1; //左結點為空,放入左結點 if (t[u].left == 0) t[u].left = a[i].second; //否則放入右結點 else t[u].right = a[i].second; //修改深度標識 t[a[i].second].depth = t[u].depth + 1; t[a[i].second].father = u; //遞迴建立子樹 dfs(a[i].second); } else if (a[i].second == u && !st[a[i].first]) { st[a[i].first] = 1; if (t[u].left == 0) t[u].left = a[i].first; else t[u].right = a[i].first; t[a[i].first].depth = t[u].depth + 1; t[a[i].first].father = u; dfs(a[i].first); } } } //最近公共祖先預設是根結點,就是1,英文簡寫:lowestCommonAncestor int lca(int x, int y) { st[x] = 1; //把x的節點記錄已走過 while (t[x].father) { //遍歷至根節點 x = t[x].father; //更新遍歷爸爸 st[x] = 1; //記錄已走過 } //遍歷至x節點已走過的節點,找到最近公共祖先 while (!st[y])y = t[y].father; return y; } int main() { //二叉樹結點個數 cin >> n; //接下來的n-1行 for (int i = 1; i < n; i++) { //構建二叉樹 cin >> x >> y; //記錄關係 a[i] = {x, y}; } //通過遞迴建樹,構建二叉樹 t[1].depth = 1, t[1].id = 1, t[1].father = 0, st[1] = 1;//根結點1 dfs(1); //表示求從結點u到結點v的距離 cin >> u >> v; //二叉樹的深度 int maxDepth = 0; for (int i = 1; i <= n; i++) maxDepth = max(maxDepth, t[i].depth); cout << maxDepth << endl; //二叉樹的寬度 int maxWidth = 0; for (int i = 1; i <= n; i++) bucket[t[i].depth]++; for (int i = 1; i <= n; i++) maxWidth = max(maxWidth, bucket[i]); cout << maxWidth << endl; //結點u到結點v間距離:結點間距離的定義:由結點向根方向(上行方向)時的邊數×2,與由根向葉結點方向(下行方向)時的邊數之和。 //這裡有一個最近公共祖先的問題,才能拿到正確答案 memset(st, 0, sizeof st); int r = lca(u, v); //按題意輸出 cout << (t[u].depth - t[r].depth) * 2 + (t[v].depth - t[r].depth) << endl; return 0; }