题目链接
分析
题目是比较好的题
首先应该想到贪心的策略,对于 i i 来说他爱的贡献是指数的即 , 那么,我们可以这样想,尽量保留最大的 i i , 而且答案要求是一个联通图,因此我们会保留 到树根路劲上所有节点。
for i = n-1 to 1,判断i是否能保留(ST 表计算他与当前答案子图的距离),
总结
- 删除叶子节点贪心算法有问题 WA7
- CF 对java 太不友好,dfs尽然爆内存
- 论缓存的重要性,将 ST表par[MAX_PAR][n] 能够利用cache 从而让我在 2995ms A 掉….
java code
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
public static final int INF = 0x3f3f3f3f;
public static final long INF64 = Long.MAX_VALUE/2;
public static final int MAXN = 1000_000+5;
public static final int MAX_PAR = 21;
public static InputReader in = new InputReader(System.in);
public static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
public static int n,retain;
public static int[][] par = new int[MAX_PAR][MAXN];
public static boolean[] vis = new boolean[MAXN];
@SuppressWarnings("unchecked")
public static ArrayList<Integer>[] G = new ArrayList[MAXN];
public static void main(String[] args) {
n = in.nextInt();
retain = n - in.nextInt();
for(int i=1 ; i<=n ; ++i)G[i] = new ArrayList<>();
for(int i=1 ; i<n ; ++i){
int a = in.nextInt();
int b = in.nextInt();
G[a].add(b);
G[b].add(a);
}
solve();
for(int i=1 ; i<=n ; ++i)
if(!vis[i])
out.print(i+" ");
out.flush();
}
public static void solve() {
findPar();
Arrays.fill(vis, false);
int num =1;
vis[n]=true;
vis[0] = true;
for(int i=n-1; i>0 ; --i){
if(vis[i])continue;
int itr =i;
int dis =1;
for(int k=MAX_PAR-1 ; k>=0 ; k--)
if(!vis[par[k][itr]]){
dis += 1 <<k;
itr = par[k][itr];
}
// System.out.println(i +" "+ dis);
itr =i;
if(dis + num <= retain){
num += dis;
while (!vis[itr]) {
vis[itr] = true;
itr = par[0][itr];
}
if(num==retain)break;
}
}
}
private static void findPar() {
Arrays.fill(vis, false);
Queue<Integer> Q = new LinkedList<>();
Q.add(n);
vis[n] = true;
par[0][n] =0;
for(int i=1 ; i<MAX_PAR ; ++i)par[i][n]=0;
while (!Q.isEmpty()) {
int p = Q.remove();
for(Integer v: G[p]){
if(vis[v])continue;
vis[v] = true;
Q.add(v);
par[0][v] =p;
}
}
for(int k=1 ; k<MAX_PAR ; ++k)
for(int i=1 ; i<=n ; ++i)
par[k][i] = par[k-1][par[k-1][i]];
}
}
class InputReader{
private final static int BUF_SZ = 32768;
BufferedReader in;
StringTokenizer tokenizer;
public InputReader(InputStream in) {
super();
this.in = new BufferedReader(new InputStreamReader(in),BUF_SZ);
tokenizer = new StringTokenizer("");
}
private String next() {
while (!tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(in.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}