*[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长度,一个一个按顺序将剩余段加入回去。

*[hackerrank]Tree Covering

#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\n", 1);

    int total = 0;

    for (int i = 1; i < n; i++) {

        if (branch.size() != 0) {

            total += branch.back();

            branch.pop_back();

        }

        printf("%d\n", total);

    }



    return 0;

}

  

你可能感兴趣的:(tree)