https://ac.nowcoder.com/acm/contest/5086/C
其实不难,让a堵在c到1的毕竟之路上就好了,需要注意,若是a和c同时到1号点就是no,同时到其他点就是yes。。。。坑了好久我的妈呀
代码公式含义:len a到c---1的必经路的长度,假设到x点
ans b到c加上c到x的路径长度
len == ans 则同时到了某个点
#include<cstring> #include<cstdio> #include<iostream> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int maxn = 1e5 + 767; struct Node { int to; int nxt; }G[maxn * 2]; int head[maxn]; int z; int n; void add(int x, int y) { G[++z].to = y; G[z].nxt = head[x]; head[x] = z; } int dep[maxn], top[maxn], fa[maxn], siz[maxn]; int son[maxn]; int dfs1(int x, int f, int d) { dep[x] = d; fa[x] = f; siz[x] = 1; int s = 0; for (int i = head[x]; i; i = G[i].nxt) { int p = G[i].to; if (p == f) continue; dfs1(p, x, d + 1); siz[x] += siz[p]; if (s < siz[p]) { s = siz[p]; son[x] = p; } } return 0; }//haah int cnt; int dfs2(int x, int t) { top[x] = t; if (!son[x]) return 0; dfs2(son[x], t);//重儿子重复利用t for (int i = head[x]; i; i = G[i].nxt) { int p = G[i].to; if (p == fa[x] || p == son[x]) continue; dfs2(p, p);//轻儿子新建t } return 0; } int LCA(int x, int y) { while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); x = fa[top[x]]; } //现在两个点在一个重链上了 if (dep[x] > dep[y]) return y; else return x; return 0; } int get(int x, int y) { int root = LCA(x, y); int c = dep[x] + dep[y] - 2 * dep[root]; return c; } int main() { int t; scanf("%d", &t); while (t--) { int m; scanf("%d %d", &n, &m); z = 0; memset(head, 0, sizeof(head)); memset(son, 0, sizeof(son)); memset(top, 0, sizeof(top)); for (int i = 1; i < n; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y); add(y, x); } dfs1(1, -1, 1); dfs2(1, 1); while (m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); int len = get(c, a) + get(1, a) - get(c, 1); len /= 2; int ans = get(b, c) + get(a, c) - len; if (ans > len) { cout << "YES "; } else if (ans == len && get(c, 1) + get(a, 1) != get(a, c)) { cout << "YES "; } else cout << "NO" << endl; } } return 0; }