标签:style blog io color os for sp div on
这个要好写点,就是dfs这棵树,将每个节点进入 和出去的位置都记录下来,
然后找 所要求得两个点最后出现的位置之间的最小值 所对应的点,就是他们的最近公共祖先。
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<vector> using namespace std; const int maxn = 111111; struct edge { int to; int next; }e[maxn*10]; int len; int head[maxn]; struct Node { int val; int id; }vis[maxn],dp[maxn][20]; int pos[maxn]; int cnt; void add(int from, int to) { e[len].to = to; e[len].next = head[from]; head[from] = len++; } void dfs(int x, int val) { vis[cnt].val = val; vis[cnt].id = x; pos[x] = cnt++; for (int i = head[x]; i != -1; i = e[i].next){ int cc = e[i].to; dfs(cc, val + 1); vis[cnt].val = val; vis[cnt].id = x; pos[x] = cnt++; } } void init(int k) { for (int i = 0; i < k; i++) dp[i][0] = vis[i]; for (int j = 1; (1 << j) <= k; j++){ for (int i = 0; i + (1 << j) - 1 < k; i++){ if (dp[i][j - 1].val < dp[i + (1 << (j - 1))][j - 1].val) dp[i][j] = dp[i][j - 1]; else dp[i][j] = dp[i + (1 << (j - 1))][j - 1]; } } } int ask(int l, int r) { int k = 0; while ((1 << (k + 1)) < r - l + 1) k++; if (dp[l][k].val < dp[r - (1 << k) + 1][k].val) return dp[l][k].id; else return dp[r - (1 << k) + 1][k].id; } int main() { map<string, int> m; map<int, string> m1; string a, b; int n; cin >> n; int sum = 1; len = 0; cnt = 0; memset(head, -1, sizeof(head)); for (int i = 0; i < n; i++){ cin >> a >> b; if (!m.count(a)) m[a] = sum, m1[sum] = a, sum++; if (!m.count(b)) m[b] = sum, m1[sum] = b, sum++; int c = m[a]; int d = m[b]; add(c, d); } dfs(1, 1); init(cnt); int q; cin >> q; while (q--){ cin >> a >> b; int c = pos[m[a]]; int d = pos[m[b]]; if (c > d) swap(c, d); cout << m1[ask(c, d)] << endl; } return 0; }
标签:style blog io color os for sp div on
原文地址:http://www.cnblogs.com/yigexigua/p/4072678.html