「TJOJ1109」张老师和石头的battle
April 22, 2018
题目描述
由于临近比赛,张老师和石头的题目还剩一道没出完,他们因为由谁出这最后一道,打起来了。他们找到了新格尔公司的天才程序员菜哭武,让菜哭武来决定谁来出最后一道题。于是菜哭武想到这样一个游戏,在一棵多叉树上面,让张老师和石头任意选择一个节点,每次让张老师先走,每次走到当前节点的父亲节点上,石头后走。当一个人走到了另一个人的祖先节点上,就算获胜,不用出这最后一道题。
输入
第一行,一个正整数 t(0<t<10),表示数据组数。
每组第一行包含两个数 N, M( N, M≤100,000),N表示树的节点数,M表示询问数,节点的编号为1到 N。
接下来 N−1行,每行2个整数 A, B (1≤A, B≤N),表示编号为 A的节点是编号为 B的节点的父亲。
接下来 M行,每行有2个数,表示 Teacher和 Stone的初始位置的编号 X, Y (1≤X, Y≤N, X≠Y),Teacher总是先移动。
输出
对于每次数据,输出 M+1行。
第一行输出 Case #t:,t表示第 t组数据
第二到第 M+1行输出每组询问获胜者的名字(顺序与输入顺序相同)。
样例输入
2 2 1 1 2 1 2 5 2 1 2 1 3 3 4 3 5 4 2 4 5
样例输出
Case #1: Teacher Case #2: Stone Teacher
题解
太久没打题,居然在这种题上RE了无数次,太菜了。
直接求个lca,比较一下距离就行了。
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> using namespace std; inline int read() { char ch = getchar(); int f = 1, x = 0; while (!(ch >= '0'&&ch <= '9')) { if (ch == '-')f = -1; ch = getchar(); } while (ch >= '0'&&ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); } return x*f; } int n, q, cnt; int deep[500001], head[500001], fa[500001][20]; bool vis[500001]; struct data { int to, next; void clear() { to = 0, next = 0; } }e[1000001]; void ins(int u, int v) { e[++cnt].to = v; e[cnt].next = head[u]; head[u] = cnt; } void insert(int u, int v) { ins(u, v); ins(v, u); } void dfs(int x) { vis[x] = 1; for (int i = 1; i <= 18; i++) { if (deep[x] < (1 << i)) break; fa[x][i] = fa[fa[x][i - 1]][i - 1]; } for (int i = head[x]; i; i = e[i].next) { if (vis[e[i].to]) continue; deep[e[i].to] = deep[x] + 1; fa[e[i].to][0] = x; dfs(e[i].to); } } int lca(int x, int y) { if (deep[x] < deep[y]) swap(x, y); int d = deep[x] - deep[y]; for (int i = 0; i <= 18; i++) if ((1 << i)&d) x = fa[x][i]; for (int i = 18; i >= 0; i--) if (fa[x][i] != fa[y][i]) { x = fa[x][i]; y = fa[y][i]; } if (x == y) return x; else return fa[x][0]; } int dis(int x, int y) { int t = lca(x, y); return deep[x] + deep[y] - 2 * deep[t]; } int main() { //freopen("a.txt", "r", stdin); int t; t = read(); for (int pp = 1; pp <= t; pp++) { memset(fa, 0, sizeof(fa)); memset(head, 0, sizeof(head)); memset(deep, 0, sizeof(deep)); memset(vis, 0, sizeof(vis)); for (int u = 0; u <= 1000000; u++) e[u].clear(); n = read(); q = read(); for (int i = 1; i < n; i++) { int u, v; u = read(); v = read(); insert(u, v); } dfs(1); cout << "Case #" << pp << ":" << endl; for (int i = 1; i <= q; i++) { int x, y; x = read(), y = read(); int deep_lca = lca(x, y); if (dis(x, deep_lca) <= dis(y, deep_lca)) printf("Teacher"); else printf("Stone"); if (pp == t && i == q) ; else printf("\n"); } } return 0; }