分析
题意就是求集合个数,满足集合所有点都是子节点和父节点关系或者不存在祖孙关系。那么可以将树拆分成若干条链,然后每次减少链数,将减少的链转化成另一种情况,也就是枚举所有链数的方案,取最小值。
对于求链数,也就是统计叶节点的个数,可以通过拓扑排序进行统计叶节点数量,然后通过删去一层叶节点来减少链数,实现了枚举所有方案。
代码
cpp
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6 + 10;
int fa[N];
int d[N];
void solve() {
int n;
cin >> n;
for(int i = 1; i <= n; i ++) {
fa[i] = 0;
d[i] = 0;
}
for(int i = 2; i <= n; i ++) {
int x;
cin >> x;
fa[i] = x;
d[i] ++;
d[x] ++;
}
queue<int> q;
for(int i = 2; i <= n; i ++) {
if(d[i] == 1) {
q.push(i);
}
d[i] --;
}
int ans = n;
int k = 0;
while(q.size()) {
int sz = q.size();
ans = min(ans, k + sz);
k ++;
while(sz --) {
int t = q.front();
q.pop();
if(fa[t] == 0) continue;
d[fa[t]] --;
if(d[fa[t]] == 0) q.push(fa[t]);
}
}
cout << ans << "\n";
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while(T --) {
solve();
}
}