CF-div3-611-F. DIY Garland 优先队列 构造树
思路
参考队友博客:https://www.cnblogs.com/AaronChang/p/12129861.html
思考如何构造一个树:(亮度低与重要度低)的二者匹配;
什么时候重要度低,就叶节点开始(从下到上)。
所以,从叶节点出发,往上构造,度数为0的就是叶节点加入优先队列,与重要度从小到大相匹配。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
/*
思考如何构造一个树:权值小的先匹配,什么时候权值小,(亮度低,重要度低)二者匹配
从叶节点出发,往上构造,度数为0的就是叶节点
*/
const int maxn = 2e5+10;
priority_queue<int,vector<int>,greater<int> > q;
vector<int> lamps; //main主灯
int deg[maxn];
int n;
vector<pair<int,int> > ans;
int main(){
cin>>n;
int root = 1; //根
for(int i=1;i<=n-1;i++){
int lamp;
cin>>lamp;
if(i == 1) root = lamp; //第一个出现的(重要性高)就是根
deg[lamp]++;
lamps.push_back(lamp);
}
for(int i=1;i<=n;i++){
if(deg[i] == 0) q.push(i); //叶节点 辐灯
}
while(!q.empty()){
int auxiliaryLamp = q.top();
q.pop();
int mainLamp = lamps[lamps.size()-1];
lamps.pop_back();
deg[mainLamp]--; //连接了一个灯 所以度数-1
if(deg[mainLamp] == 0) q.push(mainLamp); //判断是否为叶节点
ans.push_back({mainLamp,auxiliaryLamp}); //存放树的边
if(ans.size() == n-1) break;
}
cout<<root<<endl;
for(int i=ans.size()-1;i>=0;i--){
cout<<ans[i].first<<" "<<ans[i].second<<endl;
}
return 0;
}