宝藏 \operatorname{宝藏} 宝藏
题目链接: jzoj 4225 \operatorname{jzoj\ 4225} jzoj 4225
题目
输入
输出
样例输入
2
3
1 0
1 2
2
1 0 1
2 0 2 1
4
0 1
2 0
3 0
1
3 0 1 0 1
样例输出
1.0000
5.0000
<空行>
11.0000
(本人提醒:空行表示回车,要输出的是这样)
1.0000
5.0000
11.0000
数据范围
思路
这道题其实就是在我的上一篇博客——树的基础上,加一点东西。
就只是多了几次运算,要加起来,而且有几组数据。关于小数的那个,不用理他,一定是整数,就自己补充 “ . 0000 .0000 .0000” 就可以了。
代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node {
int to, nxt;
}e[200001];
int text, n, q, x, y, le[100001], KK, dep[100001], fa[21][100001], f[100001], g[100001], meet, ans, deg[100001], N;
void add(int x, int y) {
e[++KK] = (node){y, le[x]}; le[x] = KK;
e[++KK] = (node){x, le[y]}; le[y] = KK;
}
void dfsf(int father, int now) {
for (int i = le[now]; i; i = e[i].nxt)
deg[now]++;
f[now] = deg[now];
for (int i = le[now]; i; i = e[i].nxt)
if (e[i].to != father) {
dfsf(now, e[i].to);
f[now] = f[now] + f[e[i].to];
}
}
void dfsg(int father, int now) {
int sum = deg[now];
for (int i = le[now]; i; i = e[i].nxt)
if (e[i].to != father) sum = sum + f[e[i].to];
else sum = sum + g[now];
for (int i = le[now]; i; i = e[i].nxt)
if (e[i].to != father) {
g[e[i].to] = sum - f[e[i].to];
dfsg(now, e[i].to);
}
}
void dfsqian(int father, int now) {
dep[now] = dep[father] + 1;
fa[0][now] = father;
for (int i = le[now]; i; i = e[i].nxt)
if (e[i].to != father) {
f[e[i].to] = f[now] + f[e[i].to];
g[e[i].to] = g[now] + g[e[i].to];
dfsqian(now, e[i].to);
}
}
int LCA(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
for (int i = (log2(n)) + 1; i >= 0; i--)
if (dep[fa[i][x]] >= dep[y])
x = fa[i][x];
if (x == y) return x;
for (int i = (log2(n)) + 1; i >= 0; i--)
if (fa[i][x] != fa[i][y]) {
x = fa[i][x];
y = fa[i][y];
}
return fa[0][x];
}
int main() {
scanf("%d", &text);
for (int DSF = 1; DSF <= text; DSF++) {
KK = 0;
ans = 0;
memset(e, 0, sizeof(e));
memset(le, 0, sizeof(le));
memset(f, 0, sizeof(f));
memset(g, 0, sizeof(g));
memset(fa, 0, sizeof(fa));
memset(dep, 0, sizeof(dep));
memset(deg, 0, sizeof(deg));
scanf("%d", &n);
for (int i = 1; i <= n - 1; i++) {
scanf("%d %d", &x, &y);
add(x, y);
}
dfsf(0, 0);
dfsg(0, 0);
dfsqian(0, 0);
for (int i = 1; i <= 20; i++)
for (int j = 0; j <= n; j++)
fa[i][j] = fa[i - 1][fa[i - 1][j]];
scanf("%d", &q);
for (int i = 1; i <= q; i++) {
scanf("%d", &N);
if (N) scanf("%d", &x);
ans = 0;
for (int j = 2; j <= N + 1; j++) {
scanf("%d", &y);
meet = LCA(x, y);
ans += f[x] - f[meet] + g[y] - g[meet];
x = y;
}
printf("%d.0000\n", ans);
}
printf("\n");
}
return 0;
}