题解:P12652 [KOI 2024 Round 2] 拔树游戏
· 2 min read
原题链接
解题思路
拔除操作可抽象为以下过程:
- 每步输出当前根节点的权值;
- 移除根节点,并将其所有子节点加入候选集合;
- 从候选集合中选取权值最小的节点作为新根,继续执行。
设当前根为 。特殊路径的下一步必然进入 的权值最小子节点 ,并在操作后将 提升为新根。同时, 的其他子节点在后续某一步可能成为根,因此也应进入候选集合。由此得到递推过程:
- 初始时,根节点 为唯一候选;
- 每次取出候选集合的最小元素并输出;
- 将该节点的所有子节点加入集合;
- 重复直至集合为空。
由于权值互不相同,集合最小值始终与下一步特殊路径的根节点一致,该过程与题目定义完全等价。
使用优先队列维护候选集合,每个节点仅入队和出队各一次,时间复杂度为 。
参考代码
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=300005;
int a[N];
vector<int> G[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
for(int i=2;i<=n;i++)
{
int u;
cin>>u;
G[u].push_back(i);
}
for(int i=1;i<=n;i++)cin>>a[i];
priority_queue<pair<int,int>> q;
q.push({-a[1],1});
while(!q.empty())
{
auto [w,u]=q.top();
q.pop();
cout<<-w<<'\n';
for(auto v:G[u])q.push({-a[v],v});
}
return 0;
}