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

原文地址:https://www.cnblogs.com/fisherss/p/12346723.html

时间: 2024-11-14 12:26:38

CF-div3-611-F. DIY Garland 优先队列 构造树的相关文章

【cf1283F】F. DIY Garland(构造)

传送门 题意: 现有一颗有根树,每个结点\(i\)有权值\(2^i\),每条边有权值为这条边连接的深度较大的结点的子树权值和. 但现在并不知道这颗树的形态. 现在只会给出以下信息:按照边的权值从大到小进行排序,然后依次给出每条边的父亲结点. 现在要确定这颗树的形态. 思路: 假设每次给出的父亲结点为\(p_i\),那么显然\(p_1\)为根节点. 注意,因为每个结点的权值为\(2^i\),那么可以知道我们会依次找\(2^n,2^{n-1},\cdots,2^1\)这些结点的位置.根据这一点,可以

Codeforces 446B DZY Loves Modification 矩阵行列分开考虑 优先队列+构造

题目链接:点击打开链接 题意: 给定n行m列的矩阵 k次操作,一个常数p ans = 0; 对于每次操作 可以任选一行或一列, 则ans += 这行(列)的数字和 然后这行(列)上的每个数字都-=p 问最大的ans 思路: 首先我们设最终选了 行 i 次,则列选了 k-i 次 那么假设我们先全部选行,然后选列,则每次选列时,要-= i*p 这样最后是 -= i*(k-i)*p 也就是所有行对列的影响 那我们先把这个 i*(k-i)*p 提出来,那么选行和选列就互不影响 就可以分别考虑行和列 对于

D&amp;F学数据结构系列——B树(B-树和B+树)介绍

B树 定义:一棵B树T是具有如下性质的有根树: 1)每个节点X有以下域: a)n[x],当前存储在X节点中的关键字数, b)n[x]个关键字本身,以非降序存放,因此key1[x]<=key2[x]<=...<=keyn[x][x], c)leaf[x],是一个布尔值,如果x是叶子的话,则它为TRUE,如果x为一个内节点,则为FALSE. 2)每个内节点包含n[x]+1个指向其子女的指针c1[x],c2[x],...,cn[x]+1[x].叶节点没有子女,故它们的ci域无意义. 3)各关键

简洁常用权限系统的设计与实现(四):不维护level,用递归方式构造树

第三篇中,我们通过维护节点的深度level,通过迭代所有的节点,只需要一次,就构造了树.  本篇,换一种方式. 好处是:不维护节点的深度level,增加和修改节点时,也不用维护.递归实现,代码比较清晰.  坏处是:节点较多的时候,性能可能不够好.不能直接查询到节点的深度level.当然,如果需要level字段,在递归过程中,是可以计算得到的.关于在递归过程中,计算level,后面有介绍这种方法. 关于树的遍历和查找,大家都有基础,上面描述了一些总体思路,代码中有注释,基本就不用再详细介绍了. /

简洁常用权限系统的设计与实现(五):不维护节点的深度level,手动计算level,构造树

这种方式,与第三篇中介绍的类似.不同的是,数据库中不存储节点的深度level,增加和修改时,也不用维护.而是,在程序中,实时去计算的. 至于后面的,按照level升序排序,再迭代所有的节点构造树,与第三篇中的方法,完全一样.因此,本篇和下一篇,只介绍如何计算level,不再介绍后面的具体实现了. 计算level,采用递归方式. // 计算所有节点的level public static List<Map<String, Object>> caculateLevel( List<

简洁常用权限系统的设计与实现(七):一种错误的不可行的构造树的方法

前面介绍了4种方法(实质是3种),构造树. 在此,需要特别说明的是,那些都是成功的.漂亮的方法和案例 ,但实际上在解决问题的过程中,有很多其它的尝试.比如本篇介绍的方法,就是不可行的.  想说明一个道理,在走向成功的道路上,会经历很多不算太成功的事情. 我们在前面的例子中,用递归计算子结点的深度level.但实际上,我最开始想到的一种方法正好反过来了. 思路:最底层的节点level为1,如果当前节点有父结点,就把自己的level+1,递归把自己的父结点的level+1. // 计算所有节点的le

纯CSS构造树状结构图

<!doctype html> <html> <head> <meta charset="utf-8"> <title>纯CSS构造树状结构图</title> </head> <body> <div style="width:380px; height:600px; border:1px dashed gray; margin:30px auto; text-align:ce

Problem F: 时间类的构造和输出

Description 封装一个时间类Time,用于时间处理的相关功能,支持以下操作: 1. Time::Time(int,int,int)构造方法:传递时分秒的三个参数构造对象. 2. Time::showTime()方法:输出"hh:mm:ss",不足两位的要前面补0. 你设计一个时间类Time,使得main()函数能够正确运行. 函数调用格式见append.cc. append.cc中已给出main()函数. Input 输入的第一个整数n,表示有n组测试数据,每组3个整数:hh

【iOS开发-114】ABAddressBook通讯录:增删改查的简单介绍,CF框架于F框架间的转换

(1)导入ABAddressBook库,然后添加头文件后,就可以使用. --因为这个库的方法基本是C语言的风格,所以类基本是以CF开头的,比如CFStringRef以及CFArrayRef,它和OC的NSString和NSArray类似,可以相互转换,利用__bridge来强制转换,如(__bridge NSString *)XXX,就可以把原本是CFStringRef的XXX转换成NSString类型,这样做的好处就是不需要在很多地方进行释放操作CFRelease(). --使用通讯录,首先需