zoukankan      html  css  js  c++  java
  • [CF1283F] DIY Garland

    Description

    给定一棵树,编号为 i 的点权值为 2^i,定义一条边的权值为这条边链接的两个点中深度较大的点的子树的点权和。给出总点数 n,按照边权从大到小给出每条边的深度较浅的点的编号,要求构造原树。

    Solution

    边权即子树和,那么同一条直链上的边权单调,且根处最大,叶子处最小。因此排在整个序列末尾的一定是叶子结点相关的边。一个结点时叶子结点,当且仅当它不曾在原序列中出现。

    考虑一个构造过程,每一步我们会定出一条边,我们一定希望我们要定出的这条边边权最小,因此对于所有叶子结点(挂着他们的子树),维护小顶堆,权值为子树点权和,但是这样太难维护了,所以点权和直接用点自身的编号替代(题目条件的使用)。

    我们按原序列倒序遍历所有的点,对于每个点,弹出堆顶与其连边(相当于一个非叶子和叶子的配对过程),配对后的点其实就被“删除”了,这个时候如果产生了新的叶子,那么也需要将其加入堆中。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    
    
    int n,a[N],root,d[N];
    
    priority_queue <int,vector<int>,greater<int>> heap;
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n;
        for(int i=2;i<=n;i++) cin>>a[i];
    
        root=a[2];
    
        cout<<root<<endl;
    
        for(int i=2;i<=n;i++) d[a[i]]++;
    
        for(int i=1;i<=n;i++) if(d[i]==0) heap.push(i);
        for(int i=n;i>=2;i--)
        {
            int p=heap.top();
            heap.pop();
            cout<<p<<" "<<a[i]<<endl;
            d[a[i]]--;
            
            if(d[a[i]]==0) heap.push(a[i]);
        }
    }
    
  • 相关阅读:
    使用npoi做excel导出真心方便
    JAVA泛型(代码级解释)
    数据库战略高度解析(4) JDBCODBC
    [Python] 函数lambda(), filter(), map(), reduce()
    JEECG引领新的开发模式,让开发更加专注于业务!
    Parse 是什么
    Openflashchart及代理类设计介绍
    数据库战略高度解析(3) ODBC
    java 中paint .repaint.update
    svn利用钩子脚本功能实现代码同步到web目录
  • 原文地址:https://www.cnblogs.com/mollnn/p/14043993.html
Copyright © 2011-2022 走看看