题意

一二题题解 :传送门
百度之星复赛第三题题意 传送门
中文题意,自己看吧
比赛的时候看错了题意,一直没想出,赛后补题

思路

就是按照规律进行中序遍历,情况有点多所以你得分类讨论
先预处理出
每个节点的作为根节点的树的最小节点下标是多少
每个节点的作为根节点的树的节点数是多少
然后我们开始中序遍历
如果两边都有节点,找比当前节点小的最小节点的一边
如果两边的最小节点都比当前节点大那么找,节点数最小的一边遍历
如果只有一边节点,判断这一边的最小节点是否比当前节点小,是则先遍历

AC_code:

/* Algorithm: 中序遍历 Author: anthony1314 Creat Time: Time Complexity: */

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define pi acos(-1)
using namespace std;
typedef long long ll;
typedef double db;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 1e5+5;

void add(int &x, int y) {
	x = (x + y) % mod;
}
vector<int> node[maxn];
int tot;
bool ma[maxn];// 0为根节点 1不为根节点
int mr[maxn], ans[maxn], sz[maxn];//子树最小的节点 每个节点的标号 以该节点为根节点的树 的节点数
int dfs1(int root) {
	sz[root] = 1;
	int minroot = maxn+5;
	for(int i = 0; i < node[root].size(); i++) {
		int u = node[root][i];
		minroot = min(minroot, dfs1(u));
		sz[root] += sz[u];
	}
	mr[root] = minroot;
	return min(root, minroot);
}
void dfs2(int root) {
// cout<<node[root].size()<<endl;
	if(node[root].size() == 1 && min(node[root][0], mr[node[root][0]]) > root) {
		ans[root] = ++tot;
		dfs2(node[root][0]);
		return;
	} else if(node[root].size() == 2 && min(node[root][0], mr[node[root][0]]) > root
	          						 && min(node[root][1], mr[node[root][1]]) > root) {
		if(sz[node[root][0]] == sz[node[root][1]]) {
			if(min(node[root][0], mr[node[root][0]]) > min(node[root][1], mr[node[root][1]])) {
				dfs2(node[root][1]);
				ans[root] = ++tot;
				dfs2(node[root][0]);
			} else {
				dfs2(node[root][0]);
				ans[root] = ++tot;
				dfs2(node[root][1]);
			}
		} else if(sz[node[root][0]] > sz[node[root][1]]) {
			dfs2(node[root][1]);
			ans[root] = ++tot;
			dfs2(node[root][0]);
		} else {
			dfs2(node[root][0]);
			ans[root] = ++tot;
			dfs2(node[root][1]);
		}
		return;
	}
	for(int i = 0; i < node[root].size(); i++) {
		if(mr[root] == min(node[root][i], mr[node[root][i]])) {
			dfs2(node[root][i]);
		}
	}
	ans[root] = ++tot;
	for(int i = 0; i < node[root].size(); i++) {
		if(mr[root] != min(node[root][i], mr[node[root][i]])) {
			dfs2(node[root][i]);
		}
	}
}
ll slove(int n) {
	ll u = 233LL;
	ll ret = 0;
	for (ll i = 1; i <= n; i++) {
// cout<<ans[i]<<endl;
		ret = (ret + (((i ^ ans[i]) % mod) * u) % mod) % mod;
		u = (u * 233LL) % mod;
	}
	return ret;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int t, n, u, v;
	cin>>t;
	while(t--) {
		tot = 0;
		cin>>n;
		for(int i = 0; i <= n; i++) node[i].clear(), ma[i] = 0, sz[i] = 0;//初始化
		for(int i = 1; i <= n; i++) {
			cin>>u>>v;
			if(u != 0)
				node[i].push_back(u);
			if(v != 0)
				node[i].push_back(v);
			ma[u] = 1;
			ma[v] = 1;
		}
		int root;
		for(int i = 1; i <= n; i++) {
			if(ma[i] == 0) {
				root = i;
				break;
			}
		}
		dfs1(root);//预处理 遍历出深度和最小节点
		dfs2(root);//中序遍历
		cout<<slove(n)<<endl;

	}
	return 0;
}