题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6727
题解:对于当前节点,肯定分为两个区间一个在左一个在右,就把小区间分到最小编号在的那个分支中,如果当前节点最小,那就尽可能让当前节点的标号小,思路很简单,可能我写麻烦了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const ll mod = 1e9 + 7;
int nex[N][2];
int id[N];
int in[N];
int num[N][2];
int minn[N][2];
void dfs(int u) {
int to;
num[u][0] = num[u][1] = 0;
minn[u][0] = minn[u][1] = N;
if(nex[u][0]) {
to = nex[u][0];
dfs(to);
num[u][0] = num[to][0] + num[to][1] + 1;
minn[u][0] = min(minn[to][0], minn[to][1]);
minn[u][0] = min(minn[u][0], to);
}
if(nex[u][1]) {
to = nex[u][1];
dfs(to);
num[u][1] = num[to][0] + num[to][1] + 1;
minn[u][1] = min(minn[to][0], minn[to][1]);
minn[u][1] = min(minn[u][1], to);
}
// cout << u << " " << num[u][0] << " " << num[u][1] << endl;
}
int n;
void dfs1(int u, int l, int r) {
// cout << u << " " << l << " " <<r << endl;
int num1 = num[u][0];
int num2 = num[u][1];
if(num1 == 0 && num2 == 0) {
id[u] = l;
}else if(num1 == 0) {
if(minn[u][1] > u) {
id[u] = l;
if(nex[u][1]) dfs1(nex[u][1], l + 1, r);
} else {
id[u] = r;
if(nex[u][1]) dfs1(nex[u][1], l, r - 1);
}
} else if(num2 == 0) {
if(minn[u][0] > u) {
id[u] = l;
if(nex[u][0]) dfs1(nex[u][0], l + 1, r);
} else {
id[u] = r;
if(nex[u][0]) dfs1(nex[u][0], l, r - 1);
}
}
else {
if(u < minn[u][0] && u < minn[u][1]) {
if(num1 < num2 || (num1 == num2 && minn[u][0] < minn[u][1])) {
id[u] = l + num1;
if(nex[u][0]) dfs1(nex[u][0], l, l + num1 - 1);
if(nex[u][1]) dfs1(nex[u][1], l + num1 + 1, r);
} else {
id[u] = l + num2;
if(nex[u][0]) dfs1(nex[u][0], l + num2 + 1, r);
if(nex[u][1]) dfs1(nex[u][1], l, l + num2 - 1);
}
} else {
if(minn[u][0] < minn[u][1]) {
id[u] = l + num1;
if(nex[u][0]) dfs1(nex[u][0], l, l + num1 - 1);
if(nex[u][1]) dfs1(nex[u][1], l + num1 + 1, r);
} else {
id[u] = l + num2;
if(nex[u][0]) dfs1(nex[u][0], l + num2 + 1, r);
if(nex[u][1]) dfs1(nex[u][1], l, l + num2 - 1);
}
}
}
}
ll f[N];
int main() {
f[1] = 233;
for(int i = 2; i < N; i++)
f[i] = f[i - 1] * 233 % mod;
int T;
int x, y;
int rt;
scanf("%d", &T);
ll ans;
while(T--) {
scanf("%d", &n);
for(int i = 0; i <= n; i++) {
nex[i][0] = nex[i][1] = 0;
in[i] = 0;
}
for(int i = 1; i <= n; i++) {
scanf("%d %d", &x, &y);
nex[i][0] = x;
nex[i][1] = y;
in[x]++; in[y]++;
}
for(int i = 1; i <= n; i++)
if(!in[i]) {
rt = i;
break;
}
dfs(rt);
dfs1(rt, 1, n);
ans = 0;
for(int i = 1; i <= n; i++) {
// cout << id[i] << endl;
ans = (ans + (id[i] ^ i) * f[i] % mod) % mod;
}
printf("%lld\n", ans);
}
return 0;
}
/*
5
0 0
0 0
0 4
2 1
0 3
4
2 4
3 0
0 0
0 0
4
4 0
1 0
2 0
0 0
4
2 3
0 0
0 0
1 0
*/