CF1029E
一个看起来就不对的贪心居然是正解...
但仔细思考一下,这种贪心倒的确找不到反例..
贪心思想:每次找出离根节点最远的点,然后由根节点向这个点的父节点连边,一直连到所有点都能被覆盖即可,这样构造出的一定是一个可行的最优解
正确性证明(个人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的更多相关文章
- Tree with Small Distances(cf1029E)(树形动规)
You are given an undirected tree consisting of \(n\) vertices. An undirected tree is a connected und ...
- 贪心【CF1029E】Tree with Small Distances
Description 给定一棵树.要求往树中加入一些边使得从1到其他节点的距离至多是2 . 输出加入边的最小数量.(边全部都是无向的) Input 第一行一个整数n,表示树中的节点个数. 接下来n− ...
- CF1029E Tree with Small Distances
题目描述 给定一棵树.要求往树中加入一些边使得从1到其他节点的距离至多是2 . 输出加入边的最小数量.(边全部都是无向的) 题解:好多人都说是贪心,但是我写的是树形dp. (这道题实在太像小胖守皇宫了 ...
- CF1029E Tree with Small Distances (贪心)
题目大意:给你一棵边权为1的树,让你加入一些边,使得根节点(1号节点)到其他节点的最短距离不大于2 并没有想到贪心...... 正解的贪心思路是这样的 用一个堆维护当前距离最远的点,然后把根节点和它的 ...
- 树形dp——cf1029E
题解给出的是带log的,,我自己写了个on的.. #include<bits/stdc++.h> #include<vector> using namespace std; # ...
随机推荐
- sql-connectionStrings
<connectionStrings> <add name="ClassReservatConnectionString" connectionString=&q ...
- netty 在线教程
https://blog.csdn.net/qq_33314107/article/details/81321438 https://www.cnblogs.com/myJavaEE/p/679333 ...
- mysql原理~创建用户的那些事情
一 简介:mysql是如何创建用户的二 基本语法: 1 grant 权限 on db.table to 'user'@'ip' identified by 'password' 目的 创建用 ...
- linux 初识系统分区
- Django学习手册 - ORM 单表数据获取
Django 单表数据的获取: 先建立数据表格 from django.db import models # Create your models here. class userinfo(model ...
- 嵌入式开发平台迅为iTOP-4412开发板-ssh常见问题以及解决方法
一.基本网络,软件安装以及配置 ssh 软件无法登陆 Ubuntu,有可能是网络不通.SSH 软件未安装.环境变量没配置.防 火墙未关闭等. 1. 网络连接 使用 ssh 传输文件的前提是网络顺畅,即 ...
- centos 秘钥登陆配置
准备:2台机器,ip分别为:10.1.80.13 10.1.80.14 目的:通过13 ssh远程访问14.无需输入密码 1.首先在10.1.80.13上生成密钥对.cd /root/.ssh ...
- 第一次发博,发个简单的Java程序发送手机短信验证
最近在准备一个项目,想的登录时候用手机验证,就通过上网查阅了一下手机验证的实现方法,原来超级简单,下面将一步一步介绍. 1.去中国网建注册一个账号密码,首次注册送五条免费短信和3条免费彩信.具体的网址 ...
- 【Tomcat】CentOS7.0下安装多个Tomcat及其配置
安装前所需环境 在开始安装Tomcat之前,需要安装环境JDK,并配置JAVA环境.如果不知道如何配置,可参考这篇博客:[Linux]CentOS7.0下安装JDK环境 Tomcat安装 Tomcat ...
- codevs 1082 线段树练习3 (线段树)
题目: 题目描述 Description 给你N个数,有两种操作: 1:给区间[a,b]的所有数增加X 2:询问区间[a,b]的数的和. 输入描述 Input Description 第一行一个正整数 ...