codeforces980e(倍增、贪心|| 树的dfs序差分+树状数组)

探讨在给定的树形结构中,如何通过去除特定数量的节点以最大化剩余节点的总价值,同时确保剩余节点构成一棵连通的树。介绍了两种算法实现方案,包括基于DFS序的差分和树状数组查询的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

E. The Number Games

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

The nation of Panel holds an annual show called The Number Games, where each district in the nation will be represented by one contestant.

The nation has nn districts numbered from 11 to nn, each district has exactly one path connecting it to every other district. The number of fans of a contestant from district ii is equal to 2i2i.

This year, the president decided to reduce the costs. He wants to remove kk contestants from the games. However, the districts of the removed contestants will be furious and will not allow anyone to cross through their districts.

The president wants to ensure that all remaining contestants are from districts that can be reached from one another. He also wishes to maximize the total number of fans of the participating contestants.

Which contestants should the president remove?

Input

The first line of input contains two integers nn and kk (1≤k<n≤1061≤k<n≤106) — the number of districts in Panel, and the number of contestants the president wishes to remove, respectively.

The next n−1n−1 lines each contains two integers aa and bb (1≤a,b≤n1≤a,b≤n, a≠ba≠b), that describe a road that connects two different districts aa and bb in the nation. It is guaranteed that there is exactly one path between every two districts.

Output

Print kk space-separated integers: the numbers of the districts of which the contestants should be removed, in increasing order of district number.

Examples

input

Copy

6 3
2 1
2 6
4 2
5 6
2 3

output

Copy

1 3 4

input

Copy

8 4
2 6
2 7
7 8
1 2
3 1
2 4
7 5

output

Copy

1 3 4 5

Note

In the first sample, the maximum possible total number of fans is 22+25+26=10022+25+26=100. We can achieve it by removing the contestants of the districts 1, 3, and 4.

题意:给定n个点形成一棵树,序号1~n,每个点的value为2^i,现在要去掉k个点,使得其余的点还是一棵树并且值和最大,求去掉哪些点。

思路:

1、采用topo不能够得到正确答案。我们肯定是要贪心来做,保大。n必须留下作为根节点,再遍历n-1~1这几个节点,如果满足要求则把这个节点及其到根节点的枝都留下,如果不满足要求(要留下的超过了数目)则不留。在遍历一个节点的祖先节点的时候采用倍增预处理。

#include <bits/stdc++.h>  
using namespace std;  
const int maxn = 1e6 + 100;  
vector<int>tr[maxn];  
int par[maxn];  
int up[22][maxn];  
bool used[maxn];  
void dfs(int u, int fa)  
{  
    par[u] = up[0][u] = fa;  
    for(int i = 1;i<22;i++) 
        up[i][u] = up[i-1][up[i-1][u]];  
    for(int to=0;to<tr[u].size();to++) 
        if(tr[u][to]!=fa) 
            dfs(tr[u][to],u);  
}  
  
int main()  
{  
    int n, k;  
    scanf("%d %d", &n, &k);  
    for(int i=0;i<=n;i++)
        tr[i].clear();
    memset(used,0,sizeof(used));
    int u,v;
    for(int i = 1;i < n;i ++) {  
        scanf("%d %d",&u,&v);  
        tr[u].push_back(v);  
        tr[v].push_back(u);  
    }  
    dfs(n, n);  
    int all = n - k - 1;
    used[n] = 1; 
    for(int i = n-1;i;i--)
    {
        if(used[i])continue;
        int v = i,len = 1;
        for(int j = 21;j>=0;j--)
        {
            if(!used[up[j][v]])
            {
                len += (1<<j);
                v = up[j][v];
            }
        }
        if(len<=all)
        {
            all -= len;
            v = i;
            while(!used[v])
            {
                used[v] = 1;
                v = par[v];
            }
        }
    } 
    for(int i = 1;i <= n; i++) 
        if(!used[i]) printf("%d%c",i,i==n?'\n':' ');   
    return 0;  
} 

还有一种方法:利用树的dfs序(还是以n为根),可以确定一个节点的子树(前序遍历后序遍历确定),然后通过差分,增加一个节点就在这个节点子树开始位置+1,在子树结束后位置-1,这样对别的子树影响不到。通过树状数组查询可以确定这个节点的祖先节点有几个不用remove。过程还是贪心地取。

代码:http://codeforces.com/contest/980/submission/50068081

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值