zoukankan      html  css  js  c++  java
  • 题解【Codeforces1336A】Linova and Kingdom

    题面

    一开始的想法肯定就是按照深度来贪心,选深度最深的 (k) 个点,然后发现这样做其实是错误的。

    我们发现在此题中,选一个点之前肯定已经把它的所有子树中的节点全部选完了,否则先选择它的子树中的节点答案肯定更优。

    然后我们考虑计算出一个节点的贡献:

    • 选择了当前节点之后,当前节点 (i) 的幸福值为 (dep_i - 1)(dep_1 = 1))。
    • 但是 (i) 的所有子树中的节点答案都会减少 (1),因此答案还会减少 (sz_i - 1)
    • 因此节点 (i) 对答案的贡献就是 (dep_i - 1 - (sz_i - 1) = dep_i - sz_i)

    那么我们按照 (dep_i - sz_i) 从大到小排序,然后选前 (k) 大的加起来就是答案。

    注意开 ( ext{long long})

    #include <bits/stdc++.h>
    #define DEBUG fprintf(stderr, "Passing [%s] line %d
    ", __FUNCTION__, __LINE__)
    #define File(x) freopen(x".in","r",stdin); freopen(x".out","w",stdout)
    
    using namespace std;
    
    typedef long long LL;
    typedef pair <int, int> PII;
    typedef pair <int, PII> PIII;
    
    inline int gi()
    {
    	int f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    inline LL gl()
    {
    	LL f = 1, x = 0; char c = getchar();
    	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
    	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    	return f * x;
    }
    
    const int INF = 0x3f3f3f3f, N = 200003, M = N << 1;
    
    int n, k;
    int tot, head[N], ver[M], nxt[M];
    int dep[N], sz[N], ans[N];
    
    inline void add(int u, int v)
    {
        ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
    }
    
    void dfs(int u, int f)
    {
        dep[u] = dep[f] + 1, sz[u] = 1;
        for (int i = head[u]; i; i = nxt[i])
        {
            int v = ver[i];
            if (v == f) continue;
            dfs(v, u);
            sz[u] += sz[v];
        }
        ans[u] = dep[u] - sz[u];
    }
    
    int main()
    {
    	//File("");
        n = gi(), k = gi();
        for (int i = 1; i < n; i+=1) 
        {
            int u = gi(), v = gi();
            add(u, v), add(v, u);
        }
        dfs(1, 0);
        sort(ans + 1, ans + 1 + n); reverse(ans + 1, ans + 1 + n);
        LL sum = 0;
        for (int i = 1; i <= k; i+=1) sum += ans[i];
        cout << sum << endl;
    	return 0;
    }
    
  • 相关阅读:
    java学习day62-Spring boot整合Shiro配置
    java学习day62-springboot中的拦截
    java学习day62-DB项目-首页菜单动态显示
    疯狂学java的第26天
    疯狂学java的第25天
    疯狂学java的第24天
    疯狂学java的第23天
    疯狂学java的第22天
    疯狂学java的第21天
    疯狂学java的第20天
  • 原文地址:https://www.cnblogs.com/xsl19/p/12740875.html
Copyright © 2011-2022 走看看