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;
} 
posted @ 2020-02-22 19:16  fishers  阅读(168)  评论(0编辑  收藏  举报