zoukankan      html  css  js  c++  java
  • *[hackerrank]Tree Covering

    https://www.hackerrank.com/contests/illuminati/challenges/tree-covering

    这道题先是在上次交流讨论了一下,然后两位百度的朋友先写完代码share出来了,觉得是道很好的题,就做了一下。https://gist.github.com/coder32167/6964331 https://gist.github.com/snakeDling/6965299
    基本思想是贪心。根据题意,所选的点必然是叶子节点,那么首先找出树的直径,直径上的这两个点都要。找第三个点的时候,遍历所有的点,找出到直径(上任意一点)距离最小的叶子节点,接着以此类推找第四个点。
    贪心可行的依据可直观的这么看,假设AB是树的直径,那么从树中任意一其他叶子X出发寻找最长路,要么是AX,要么是BX。这个是广为证明的一个结论,已经用于寻找直径了。
    接下来就是实现,怎么求第三个点,第四个点呢。答案是递归BFS,递归到叶子节点时cover是1,然后往上回溯。对任意父节点,取子节点中cover数最大的加一,剩下的都放入vector中,最后排序。(或者放入堆中也可,就不用最后排序了。)
    最后依次把这些branch加回去。过程如下示意图展示:就是先取直径上任意一点,然后根据BFS得到的排序的branch长度,一个一个按顺序将剩余段加入回去。

    #include <cstdio>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    
    using namespace std;
    
    int get_root(vector<vector<int>> &tree, int root) {
        int n = tree.size();
        vector<bool> visit(n, false);
        vector<int> len(n);
        queue<int> que;
    
        int max_len = 1;
        que.push(root);
        len[root] = 1;
        while (!que.empty()) {
            int node = que.front();
            que.pop();
            if (visit[node]) 
                continue;
            visit[node] = true;
            int m = tree[node].size();
            if (len[node] > max_len) {
                root = node;
                max_len = len[node];
            }
            for (int i = 0; i < m; i++) {
                que.push(tree[node][i]);
                len[tree[node][i]] = len[node] + 1;
            }
        }
        return root;
    }
    
    int collect_branch(vector<vector<int>> &tree, int root, vector<int> &branch, vector<bool> &visit) {   
        visit[root] = true;
        int m = tree[root].size();
        vector<int> result;
        for (int i = 0; i < m; i++) {
            if (visit[tree[root][i]])
                continue;
            int len = collect_branch(tree, tree[root][i], branch, visit);
            result.push_back(len);
        }
        if (result.size() == 0)
            return 1;
        sort(result.begin(), result.end());
        int ret = result.back();
        result.pop_back();
        for (int i = 0; i < result.size(); i++) {
            branch.push_back(result[i]);
        }
        return ret + 1;
    }
    
    int main()
    {
        int n;
        scanf("%d", &n);
        vector<vector<int>> tree(n+1);
        for (int i = 1; i < n; i++) {
            int a, b;
            scanf("%d", &a);
            scanf("%d", &b);
            tree[a].push_back(b);
            tree[b].push_back(a);
        }
    
        int root = get_root(tree, 1);
        vector<int> branch;
        vector<bool> visit(n+1, false);
        int main_branch = collect_branch(tree, root, branch, visit);
        branch.push_back(main_branch);
        sort(branch.begin(), branch.end());
    
        printf("%d
    ", 1);
        int total = 0;
        for (int i = 1; i < n; i++) {
            if (branch.size() != 0) {
                total += branch.back();
                branch.pop_back();
            }
            printf("%d
    ", total);
        }
    
        return 0;
    }
    

      

  • 相关阅读:
    做淘宝直通车怎么提高宝贝的点击率?
    如何更有效的优化直通车关键词?为什么要优化?
    淘宝直通车运营的6个技巧与逻辑
    淘宝直通车推广技巧,如何做好养词及关键词出价
    淘宝直通车技巧干货大全
    直通车 直接成交笔数,间接成交笔数
    直通车关键字竞争透视
    影响淘宝综合排名的因素有哪些?
    影响淘宝排名的因素有哪些
    面试-java反射
  • 原文地址:https://www.cnblogs.com/lautsie/p/3369448.html
Copyright © 2011-2022 走看看