一个看起来就不对的贪心居然是正解...

但仔细思考一下,这种贪心倒的确找不到反例..

贪心思想:每次找出离根节点最远的点,然后由根节点向这个点的父节点连边,一直连到所有点都能被覆盖即可,这样构造出的一定是一个可行的最优解

正确性证明(个人YY):

主要是要证明这种做法的最优性:

首先,由于所有点都要求被覆盖,自然离根节点最远的点也不例外

那么,如果想覆盖上离根节点最远的点,只会有两种覆盖方法:一种是将根节点与这个点本身相连,另一种是将根节点与这个点的父节点相连

不难发现,将根节点与这个点的父节点相连,这样的方案一定不会差

证明:假设这个父节点还有别的子节点,那么与父节点相连后这些子节点都能被覆盖,这样一定是更优的

而即使这个父节点没有别的子节点,他还有自己的父节点,这样连边也能减少根节点与他的父节点的距离,也会达到更好的效果

即使上面两点都没有起作用,至少这样还可以覆盖上最远的点,也并不会使代价增大,所以这样做是完全可行的。

这样就完事了

(ps:树上bfs真好用)

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct Edge
{
int next;
int to;
}edge[400005];
bool used[200005];
int head[200005];
int f[200005];
int n;
int cnt=1;
void init()
{
memset(head,-1,sizeof(head));
cnt=1;
}
void add(int l,int r)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
head[l]=cnt++;
}
struct node
{
int num;
int dep;
}p[200005];
void bfs(int rt)
{
queue <int> M;
p[rt].dep=0;
p[rt].num=rt;
M.push(rt);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(p[to].dep)
{
continue;
}
p[to].dep=p[u].dep+1;
p[to].num=to;
f[to]=u;
M.push(to);
if(p[to].dep<=2)
{
used[to]=1;
}
}
}
}
bool cmp(node a,node b)
{
return a.dep>b.dep;
}
int main()
{
scanf("%d",&n);
init();
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
bfs(1);
sort(p+1,p+n+1,cmp);
int ans=0;
for(int i=1;i<=n;i++)
{
if(used[p[i].num])
{
continue;
}
ans++;
int u=f[p[i].num];
used[u]=1;
for(int j=head[u];j!=-1;j=edge[j].next)
{
int to=edge[j].to;
used[to]=1;
}
}
printf("%d\n",ans);
return 0;
}

CF1029E的更多相关文章

  1. Tree with Small Distances(cf1029E)(树形动规)

    You are given an undirected tree consisting of \(n\) vertices. An undirected tree is a connected und ...

  2. 贪心【CF1029E】Tree with Small Distances

    Description 给定一棵树.要求往树中加入一些边使得从1到其他节点的距离至多是2 . 输出加入边的最小数量.(边全部都是无向的) Input 第一行一个整数n,表示树中的节点个数. 接下来n− ...

  3. CF1029E Tree with Small Distances

    题目描述 给定一棵树.要求往树中加入一些边使得从1到其他节点的距离至多是2 . 输出加入边的最小数量.(边全部都是无向的) 题解:好多人都说是贪心,但是我写的是树形dp. (这道题实在太像小胖守皇宫了 ...

  4. CF1029E Tree with Small Distances (贪心)

    题目大意:给你一棵边权为1的树,让你加入一些边,使得根节点(1号节点)到其他节点的最短距离不大于2 并没有想到贪心...... 正解的贪心思路是这样的 用一个堆维护当前距离最远的点,然后把根节点和它的 ...

  5. 树形dp——cf1029E

    题解给出的是带log的,,我自己写了个on的.. #include<bits/stdc++.h> #include<vector> using namespace std; # ...

随机推荐

  1. K - Subarrays OR Gym - 102152K (思维)

    题目链接: K - Subarrays OR Gym - 102152K 题目大意:T组测试样例,然后n个数,让你求每一个l,r中有多少个不同的异或值. 具体思路: 对于(1,i)这个区间, 我们当前 ...

  2. truncate、delete、drop区别

    语法: truncate table 表名 delete from 表名 drop table 表名 应用范围: truncate 只能对表,且不能用于参与了索引的表,不能用于外键约束引用的表 del ...

  3. android java 字符串正则表达式 分离特殊字符串

    Java中正则表达式的使用 在Java中,我们为了查找某个给定字符串中是否有需要查找的某个字符或者子字串.或者对字符串进行分割.或者对字符串一些字符进行替换/删除,一般会通过if-else.for 的 ...

  4. Vue & webpack

    在webpack构建的项目中使用vue进行开发 在入口文件中 import Vue from 'vue' 导入的构造函数,功能不完整,只提供了runtime-only的方式,并没有提供网页中那样的使用 ...

  5. Mysql多实例安装笔记

    参考: 系统:KaliLinux (x86_64) 软件下载 1.下载地址: 2.选择5.6版本 安装 1.准备文件和目录 tar -zxvf mysql-5.6.40-linux-glibc2.12 ...

  6. sqlmap 使用笔记

    1.sqlmap -hh 查看详细说明 2.使用google proxychains sqlmap -g " inurl:\".php?id=1\" " 自动发 ...

  7. C++拷贝构造函数(深拷贝&浅拷贝)

    对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=88; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.下面看一个类对象拷贝的简单例子. ...

  8. 【转】python模块分析之collections(六)

    [转]python模块分析之collections(六) collections是Python内建的一个集合模块,提供了许多有用的集合类. 系列文章 python模块分析之random(一) pyth ...

  9. Scala 继承

    1. 继承 Scala 通过 extends 关键字来继承类. 那么继承一个类有什么好处呢? 子类拥有继承自超类的方法和字段(即为val(常量), var(变量)所定义的) 可以添加自己需要的新方法和 ...

  10. unigui 在单据中,某输入为必填项的 JS代码

     给大家分享下在单据中,某输入为必填项,用红框标示的简单处理方法:UniSession.AddJS(UniEdit1.JSName+ '.el.setStyle({"border" ...