HDU 5242 Game(树上贪心)
题目链接 Game
题目的意思很简单, 就是要找一棵树权值最大等等前K条链。
在本题中,走的次数等于min(叶子结点个数,k)
tree[i].sum意为从i号结点出发走到某个叶子结点能得到的最大总价值。
pson[i]表示i号结点若要获得最大价值那么下一步该怎么走。
显然tree[i].sum和pson[i]是从i的各个儿子转移得到的。
那么先做一遍DFS计算出tree[i].sum, 再排序。
然后贪心,从价值最大的那个结点开始选,从大到小。
选的时候,要把他中途经过的结点全部屏蔽(就是说被屏蔽的结点接下来不能被选了)。
当选的次数到达k或者没有结点可选时那就停止。
具体可以看我的代码。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 7 #define dec(i,a,b) for(int i(a); i >= (b); --i) 8 #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) 9 10 #define LL long long 11 12 const int N = 100000 + 10; 13 const int M = 10000 + 10; 14 const int A = 30 + 1; 15 16 struct Node{ 17 LL sum; int id; 18 friend bool operator < (const Node &a, Node &b){ 19 return a.sum > b.sum; 20 } 21 } tree[N]; 22 23 int E[N << 2], X[N << 2], H[N << 2], pson[N]; 24 bool isleaf[N], v[N], vc[N]; 25 LL a[N], c[N], ans; 26 int T, n, k, et, x, y, num; 27 int Case = 0; 28 int cnt = 0; 29 30 bool cmp(LL a, LL b){ return a > b;} 31 32 inline void addedge(int a, int b){ 33 E[++et] = b, X[et] = H[a], H[a] = et; 34 } 35 36 void dfs(int x, int fa){ 37 LL cnt = 0, tot = 0, w = 0; 38 tree[x].sum = a[x]; 39 for_edge(i, x) if (E[i] != fa){ 40 int u = E[i]; ++cnt; 41 dfs(u, x); 42 if (tree[u].sum > tot){ tot = tree[u].sum; w = u;} 43 } 44 pson[x] = w; 45 if (cnt == 0) isleaf[x] = true; 46 else tree[x].sum += tree[w].sum; 47 } 48 49 void tag(int x){ 50 v[x] = false; 51 if (!isleaf[x]) tag(pson[x]); 52 } 53 54 int main(){ 55 56 scanf("%d", &T); 57 while (T--){ 58 et = 0; num = 0; 59 scanf("%d%d", &n, &k); 60 memset(H, 0, sizeof H); 61 memset(c, 0, sizeof c); 62 memset(pson, 0, sizeof pson); 63 memset(vc, false, sizeof vc); 64 memset(isleaf, false, sizeof isleaf); 65 rep(i, 1, n) scanf("%lld", a + i); 66 rep(i, 1, n - 1){ 67 scanf("%d%d", &x, &y); 68 addedge(x, y); addedge(y, x); 69 vc[y] = true; 70 } 71 rep(i, 1, n) tree[i].id = i; 72 dfs(1, 0); 73 sort(tree + 1, tree + n + 1); 74 memset(v, true, sizeof v); 75 cnt = 0; ans = 0; 76 rep(i, 1, n) if (v[tree[i].id] && cnt < k){ 77 ans += tree[i].sum; 78 tag(tree[i].id); 79 ++cnt; 80 } 81 82 printf("Case #%d: %lld\n", ++Case, ans); 83 84 } 85 86 return 0; 87 88 }