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;
} 

猜你喜欢

转载自www.cnblogs.com/fisherss/p/12346723.html