980E The Number Games(貪心+樹上倍增)
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 aaand 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.
題意:給你一棵樹,樹上的點的權值為2^i,問你保留K個點,使得保留的點都是聯通的,並且點權和最大。
解題思路:明顯貪心,肯定是先從N開始取,一直取到1,,所以對於每一個點,我們貪心的取,如何保證聯通呢?暴力的查詢離他最近的已經被取的點,因為我們先取N,那就以N為根,那麼就變成了暴力往上走,遇到的第一個已經取的點的時候經過的點都要取。這裡暴力往上走然後取點就好了。但是,我們有K限制,所以暴力往上走可能會超過了K,那麼就白走了,所以我們先用倍增判斷往上走是否可行,不可行的話直接下一個點。
#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
#include <set>
#include <stdio.h>
#include <map>
#include <bitset>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int MAXN = 2000005;
int N,K;
vector<int> G[MAXN];
int fa[20][MAXN];
void dfs(int u,int pre){
fa[0][u]=pre;
for(int i=1;i<20;i++)
fa[i][u]=fa[i-1][fa[i-1][u]];
for(int i=0;i<G[u].size();i++){
if(G[u][i]!=pre)
dfs(G[u][i],u);
}
}
bool vis[MAXN];
int main()
{
scanf("%d%d",&N,&K);
int u,v;
for(int i=0;i<N-1;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(N,N);
K=N-K-1;
vis[N]=1;
for(int i=N-1;i>=1;i--){
if(vis[i])
continue;
int tmp=i;
int sum=0;
for(int j=19;j>=0;j--){
if(!vis[fa[j][tmp]]){
tmp=fa[j][tmp];
sum+=(1<<j);
}
}
sum++;
if(sum<=K){
K-=sum;
tmp=i;
while(!vis[tmp]){
vis[tmp]=1;
tmp=fa[0][tmp];
}
}
}
for(int i=1;i<=N;i++)
if(!vis[i])
printf("%d ",i);
return 0;
}