杭电第九场
Problem A
思路:
求出所有叶子的子节点,然后依次连边,并选择最优的情况即可
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5 * 1e5 + 10;
ll son[N];
vector<int> tree[N];
ll sum_edge, init_edge;
ll res;
int n;
ll dfs(int root){
ll sum = 1;
for(int i = 0; i < tree[root].size(); i++)
sum += dfs(tree[root][i]);
son[root] = sum;
init_edge += sum;
return sum;
}
void travers(int step, int root){
res += son[root];
if(!tree[root].size()){//遍历到叶子节点
ll k = (ll)n * step + init_edge - res;
sum_edge = max(sum_edge, k);
res -= 1;
return ;
}
for(int i = 0; i < tree[root].size(); i++)
travers(step + 1, tree[root][i]);
res -= son[root];
return ;
}
int main ( ){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T; cin >> T;
while(T--){
cin >> n;
for(int i = 0; i <= n; i++){
tree[i].clear();
son[i] = 0;
}
init_edge = 0;
res = 0;
for(int i = 1; i < n; i++){
int x; cin >> x;
tree[x].push_back(i + 1);
}
dfs(1);
sum_edge = init_edge;
travers(1, 1);
cout << sum_edge << endl;
}
return 0;
}