其实这个没什么好说的啦。。。就相当于一种很妙的树hash
好像在NOIWC有出过。。。
就是这个是个双射,且一一对应
就每次找编号最小的叶子节点,删掉,迭代至只剩一个点
也可以从prufer变为原树
注意,以某个点为根,要在最后一位添一位,并且那个根不能找父亲。。。
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
左右。。
还有一个
O
(
n
)
O(n)
O(n)的假做法,但可能会被卡成
O
(
n
2
)
O(n^2)
O(n2)。。。。
你想看可以去洛谷找。。。
不然我贴个连接
#include<bits/stdc++.h>
#define MAXN 5000005
typedef long long ll;
using namespace std;
ll n,m,tot,ans = 0;
ll in[MAXN],fa[MAXN],g[MAXN],prufer[MAXN];
struct node{
ll id;
friend bool operator < (node x , node y){
return x.id > y.id;
}
};
priority_queue<node>q;
set<ll>num;
int main(){
cin>>n>>m;memset(in , 0 , sizeof(in));
if(m == 1){
for(int i = 1 ; i < n ; i++)scanf("%d" , &fa[i]) , in[fa[i]]++;
for(int i = 1 ; i <= n ; i++){
if(!in[i])q.push((node){i});
}
for(int i = 1 ; i <= n - 2 ; i++){
ll now = q.top().id;q.pop();
g[i] = fa[now];
in[fa[now]]--;
if(!in[fa[now]])q.push((node){fa[now]});
ans = ans ^ (i * g[i]);
}
cout<<ans<<endl;
exit(0);
}
else{
for(int i = 1 ; i <= n - 2 ; i++)scanf("%d" , &prufer[i]) , in[prufer[i]]++;
prufer[n - 1] = n;
for(int i = 1 ; i < n ; i++)if(!in[i])num.insert(i);
for(int i = 1 ; i < n ; i++){
ll zz = *num.begin();
num.erase(zz);
fa[zz] = prufer[i];
in[prufer[i]]--;
if(!in[prufer[i]] && prufer[i] != n)num.insert(prufer[i]);
}
for(int i = 1 ; i < n ; i++)ans = ans ^ (i * fa[i]);
cout<<ans<<endl;
}
}