codeforces 980E The Number Games

Title:

Given a tree, it is required to remove k points, so that the rest is still a tree, and Σ(2^i) is required to be the largest, i is the number of the remaining nodes.

Ideas:

To maximize the sum of the powers of 2 of the remaining points, you must keep the large points, which is greedy.

If you consider which points to remove, then if you remove a point, the points of the subtree connected to it must be removed, which is very troublesome.

So let's consider which points to keep, then consider whether to keep the current points from big to small. And mark the reserved points.

First of all, the point n can definitely be reserved, marked, and then consider n-1, n-2 in turn. . . 1.

For the current point, determine whether it has been marked. If not, find the unmarked ancestor farthest from the current point. If this point is to be marked, the total added points are from the current point to the current point. The number of all points on the path of the farthest unmarked ancestor, which can also be interpreted as points on the path from the current point to the tree of points that have been reserved.

When looking for this path, if it is violent, n^2 will definitely be T, so you can first use multiplication preprocessing, and then find the ancestors, and the complexity can be reduced to O(nlogn).

If this number does not exceed the requirement, then mark all points on the path.

The last unmarked point is the point to discard.

Code:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <vector>
 5 using namespace std;
 6 const int N = 1e6 + 10;
 7 int n,k;
 8 vector<int> g[N];
 9 int fa[N];
10 int dep[N];
11 bool vis[N];
12 int anc[N][35];
13 void dfs(int u,int f)
14 {
15     fa[u] = f;
16     for (int v : g[u])
17     {
18         if (v != f)
19         {
20             dep[v] = dep[u] + 1;
21             dfs(v,u);
22         }
23     }
24 }
25 void rdfs(int u,int f)
26 {
27     vis[u] = 1;
28     if (u == f) return;
29     rdfs(fa[u],f);
30 }
31 void preprocess()
32 {
33     for (int i = 0;i < n;i++)
34     {
35         anc[i][0] = fa[i];
36         for (int j = 1;(1<<j) < n;j++) anc[i][j] = -1;
37     }
38     for (int j = 1;(1<<j) < n;j++)
39     {
40         for (int i = 0;i < n;i++)
41         {
42             if (anc[i][j-1] != -1)
43             {
44                 int a = anc[i][j-1];
45                 anc[i][j] = anc[a][j-1];
46             }
47         }
48     }
49 }
50 int main()
51 {
52     memset(anc,-1,sizeof(anc));
53     scanf("%d%d",&n,&k);
54     k = n - k;
55     for (int i = 1;i < n;i++)
56     {
57         int x,y;
58         scanf("%d%d",&x,&y);
59         x--,y--;
60         g[x].push_back(y);
61         g[y].push_back(x);
62     }
63     dfs(n-1,-1);
64      preprocess();
 65      int num = 1 ;
 66      vis[n- 1 ] = 1 ;
 67      for ( int i = n - 2 ;i >= 0 ;i-- )
 68      {
 69          if (vis[i]) continue ;
 70          int t = i;
 71          for ( int j = 20 ;j >= 0 ;j-- )//j is an enumeration from big to small
 72          {
 73              if (anc[t][j] == - 1) continue;
74             else
75             {
76                 if (!vis[anc[t][j]])
77                 {
78                     t = anc[t][j];
79                 }
80             }
81         }
82         if (dep[i] - dep[t] + 1 + num <= k)
83         {
84             num += dep[i] - dep[t] + 1;
85             rdfs(i,t);
86         }
87     }
88     for (int i = 0;i < n;i++)
89     {
90         if (!vis[i]) printf("%d ",i+1);
91     }
92     return 0;
93 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326369484&siteId=291194637