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\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;
}

  

*[hackerrank]Tree Covering的更多相关文章

  1. hackerrank答案

    regex: https://github.com/taiyang-li/hackerrank/tree/master/hackerrank/regex-exercise awk: https://g ...

  2. Finding Memory Leaks with SAP Memory Analyzer

    Introduction There is a common understanding that a single snapshot of the java heap is not enough f ...

  3. HackerRank "Self Balancing Tree"

    Something to learn: Rotation ops in AVL tree does not require recursion. https://github.com/andreima ...

  4. *[hackerrank]Cut the tree

    https://www.hackerrank.com/contests/w2/challenges/cut-the-tree 树分成两部分,求两部分差最小.一开始想多了,后来其实求一下总和,求一下分部 ...

  5. 【HackerRank】Cut the tree

    题目链接:Cut the tree 题解:题目要求求一条边,去掉这条边后得到的两棵树的节点和差的绝对值最小. 暴力求解会超时. 如果我们可以求出以每个节点为根的子树的节点之和,那么当我们去掉一条边(a ...

  6. 【HackerRank】Utopian tree

    The Utopian tree goes through 2 cycles of growth every year. The first growth cycle of the tree occu ...

  7. HackerRank "Kundu and Tree" !!

    Learnt from here: http://www.cnblogs.com/lautsie/p/3798165.html Idea is: we union all pure black edg ...

  8. HackerRank "The Indian Job"

    A sly knapsack problem in disguise! Thanks to https://github.com/bhajunsingh/programming-challanges/ ...

  9. HackerRank "Array and simple queries" !

    The most interesting, flexible and juicy binary tree problem I have ever seen. I learnt it from here ...

随机推荐

  1. ReadWriteLock与ReentrantReadWriteLock

    JAVA的JUC包中的锁包括"独占锁"和"共享锁".JUC中的共享锁有:CountDownLatch.CyclicBarrier.Semaphore.Reent ...

  2. 获取tcl开发工具

    本篇文章对tcl脚本的解释工具获取和编辑工具进行一个简单的介绍,工欲善其事,必先利其器,掌握好解释工具的用法,能够使后续的脚本开发工作更加顺利.从源代码的获取到编译,详细解释在linux和window ...

  3. C# 右键菜单 contextMenuStrip

    1.添加contextMenuStrip控件 默认命名:contextMenuStrip1 2.在要显示的控件上,找到其ContextMenuStrip属性,并设置其为contextMenuStrip ...

  4. 如何使用SC命令添加删除服务

    1.如何删除服务 cmd然后再输入 sc delete "服务名称" 后,回车,双引号必须为英文符号. 2.添加服务 sc create ServiceName binPath= ...

  5. 利用putty实现文件在linux上传和下载

    利用putty实现文件上传和下载:1.打开windows命令提示符窗口d:(putty在d盘下)cd putty(pscp.exe所在目录)2:上传(主要利用pscp程序)pscp d:/jdk-8u ...

  6. scrapy抓取到中文,保存到json文件为unicode,如何解决.

    http://scrapy-chs.readthedocs.org/zh_CN/latest/intro/overview.html 以上链接是很好的scrapy学些资料.感谢marchtea的翻译. ...

  7. OpenCV学习(1)-安装(Windows)

    下载安装 在这里下载.我下载了2.4.9的Windows版本.双击安装即可. 配置环境变量 配置环境变量的目的是为了让系统找到OpenCV的动态链接库.因此需要把动态链接库添加到系统环境变量PATH中 ...

  8. (转)linux多线程,线程的分离与结合

    转自:http://www.cnblogs.com/mydomain/archive/2011/08/14/2138454.htm 线程的分离与结合     在任何一个时间点上,线程是可结合的(joi ...

  9. 24种设计模式--组合模式【Composite Pattern】

    大家在上学的时候应该都学过“数据结构”这门课程吧,还记得其中有一节叫“二叉树”吧,我们上学那会儿这一章节是必考内容,左子树,右子树,什么先序遍历后序遍历什么,重点就是二叉树的的遍历,我还记得当时老师就 ...

  10. [翻译][MVC 5 + EF 6] 1:创建数据模型

    原文:Getting Started with Entity Framework 6 Code First using MVC 5 1.新建MVC项目: 2.修改Views\Shared\_Layou ...