zoukankan      html  css  js  c++  java
  • CodeForces

     

        题意大概就是,给你一棵树,让你选择一个N-K个节点的联通块,使得联通块内点权和最大,同时规定第i个点的权值是2^i。

     

        因为点权都是2^i,很特殊,所以可以直接贪心。选一个有n的联通块的最后的权值肯定要大于没有选的,所以可以先想到如下算法:

     

            我们从n到1依次尝试把 不在当前联通块内的点 加入 到当前联通块中去(初始的联通块为空),我们只需要找到当前联通块中离这个点最近的一个点,然后判断一下 当前联通块大小 + 这两点间路径长度(也就是加入这个点后联通块大小的增量) 是否<=k,   是的话就加入,并把路径上所有点都加入当前联通块;否则不进行任何操作。

     

        因为一开始联通块是空的,所以我们可以先把点n加入然后再考虑剩下的,由此,我们就可以设计一个较上述算法更加简单的算法:

     

            以n为根建有根树,这样上述算法找 离待加入的点最近的 当前联通块内的点 的过程 就变成了   找一个点到根路径上第一个被选的点(这个其实yy一下就想出来了嘛hhhh),因为始终可以证明,当一个点被选的时候它的爸爸也一定被选了。

     

        然后就可以直接树剖找第一个被选的祖先,暴力染色(选点)。

    Discription

    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 kkcontestants 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 (1k<n1061≤k<n≤106) — the number of districts in Panel, and the number of contestants the president wishes to remove, respectively.

    The next n1n−1 lines each contains two integers aa and bb (1a,bn1≤a,b≤n, aba≠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
    6 3
    2 1
    2 6
    4 2
    5 6
    2 3
    Output
    1 3 4
    Input
    8 4
    2 6
    2 7
    7 8
    1 2
    3 1
    2 4
    7 5
    Output
    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.

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=1000005;
    int to[maxn*2],ne[maxn*2],hd[maxn],num,dep[maxn];
    int n,K,siz[maxn],son[maxn],T[maxn],F[maxn];
    int dfn[maxn],dy[maxn],dc=0;
    bool IP[maxn];
    inline void add(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num;}
    inline int read(){
    	int x=0; char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar());
    	for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
    	return x;
    }
    void W(int x){ if(x>=10) W(x/10); putchar(x%10+'0');}
    
    void Fdfs(int x,int fa){
    	siz[x]=1,F[x]=fa;
    	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){
    		dep[to[i]]=dep[x]+1,Fdfs(to[i],x),siz[x]+=siz[to[i]];
    		if(!son[x]||siz[to[i]]>siz[son[x]]) son[x]=to[i];
    	}
    }
    
    void Sdfs(int x,int tp){
    	T[x]=tp,dfn[x]=++dc,dy[dc]=x;
    	if(!son[x]) return;
    	Sdfs(son[x],tp);
    	
    	for(int i=hd[x];i;i=ne[i]) if(to[i]!=son[x]&&to[i]!=F[x]) Sdfs(to[i],to[i]);
    }
    
    inline int getdeep(int x){
    	int ans=dep[x],L,R,MID;
    	
    	while(!IP[x]){
    		if(!IP[T[x]]) x=F[T[x]];
    		else{
    			L=dfn[T[x]],R=dfn[x];
    			while(L<=R){
    				MID=L+R>>1;
    				if(IP[dy[MID]]) x=dy[MID],L=MID+1;
    				else R=MID-1;
    			}
    		}
    	}
    	
    	return ans-dep[x];
    }
    
    inline void paint(int x){
    	while(!IP[x]) IP[x]=1,x=F[x];
    }
    
    inline void solve(){
    	for(int i=n-1,now;i;i--) if(!IP[i]){
    		now=getdeep(i);
    		if(now<=K) K-=now,paint(i);
    	}
    }
    
    int main(){
    	scanf("%d%d",&n,&K),K=n-K;
    	int uu,vv;
    	for(int i=1;i<n;i++) scanf("%d%d",&uu,&vv),add(uu,vv),add(vv,uu);
    	Fdfs(n,0),Sdfs(n,n);
    	
    	IP[n]=1,K--;
    	solve();
    	
    	for(int i=1;i<=n;i++) if(!IP[i]) W(i),putchar(' ');
    	return 0;
    }
    

      

     

  • 相关阅读:
    Android生成自定义二维码
    Android快速实现二维码扫描--Zbar
    设计模式-桥接模式
    设计模式-组合模式
    设计模式-享元模式
    设计模式-适配器模式
    设计模式-装饰者模式
    设计模式-门面(外观)模式
    设计模式-原型模式
    设计模式-单例模式
  • 原文地址:https://www.cnblogs.com/JYYHH/p/9032554.html
Copyright © 2011-2022 走看看