题面

给定 n 个节点的有根树,根是 1 号节点。

你可以选择 k 个节点将其设置为工业城市,其余设置为旅游城市。

对于一个工业城市,定义它的幸福值为工业城市到根的路径经过的旅游城市的数量。

你需要求出所有工业城市的幸福值之和的最大可能值。

\(1<=k<=n<=2*10^5\);

传送门

题解

仔细想想不难想到,肯定是从叶子节点这种深度大的选

然后做法就是排遍序,然后按深度从大到小选???

但是,真的是这样吗???

我们仔细考虑一个点作为工业城市的条件与情况:

首先,假如以此点为根的子树中还有点没有被选,那么这一个点肯定不是当前最优决策

有了上面这一条,我们可以推出:

一个点被选工业城市的前提是它的儿子都已经被选了

然后我们来考虑将一个点选为工业城市的贡献:

  • 它的深度
  • 它会使得它的子树中每个已被选为工业城市的点贡献-1

又因为该点子树中肯定每个点都已经是工业城市,所以该点贡献value就是:

\(value=它的深度-子树大小\)

按照这个\(value\)维护一个大根堆,将每个儿子都已被选或本身为叶子节点的点插入就好

代码

#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define ll long long
#define get getchar()
in int read()
{
int t=0,x=1;char ch=get;
while((ch<'0'||ch>'9')&&ch!='-')ch=get;
if(ch=='-')x=-1,ch=get;
while(ch<='9'&&ch>='0')t=t*10+ch-'0',ch=get;
return x*t;
}
const int _=2e6+5;
struct edge{
int to,ne;
}e[_];
struct dian{
int id,deep;
}d[_];
int h[_],n,k,num[_],tot,father[_];
in void add(int x,int y)
{
e[++tot].to=y,e[tot].ne=h[x],h[x]=tot;
}
int val[_],siz[_],len[_];
in void dfs(int u,int fa)
{
d[u].id=u,d[u].deep=d[fa].deep+1;
siz[u]=1;father[u]=fa;
for(re int i=h[u];i;i=e[i].ne)
{
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
}
}
in int cmp(dian a,dian b)
{
return a.deep>b.deep;
}
in ll work(int x)
{
return (d[x].deep-1)-siz[x]+1;
}
priority_queue<pair<ll,int> >q;
in void dfs2(int u,int fa)
{
len[u]+=len[fa];
if(!val[u]) len[u]++;
for(re int i=h[u];i;i=e[i].ne)
{
int v=e[i].to;
if(v==fa) continue;
dfs2(v,u);
}
}
int main()
{
n=read(),k=read();
for(re int i=1;i<n;i++)
{
int x=read(),y=read();
add(x,y),add(y,x);
num[x]++,num[y]++; //统计每个点的度数,之后要统计哪些点成为"叶子"节点
}
dfs(1,0); //求深度、子树大小、父亲节点编号
for(re int i=1;i<=n;i++)
if(num[i]==1)
q.push(make_pair(work(i),i)); //把真正的叶子加入优先队列
while(k--)
{
int u=q.top().second;q.pop();
val[u]=1;num[father[u]]--; //val[i]为1 表示此点已是工业城市;将父亲节点的度数-1
if(1==num[father[u]]) //若父亲节点度数为1,则说明父亲节点的所有儿子都已经成为了工业城市,所以该父亲节点也有了“候选资格”
q.push(make_pair(work(father[u]),father[u]));
}
dfs2(1,0); //统计每个工业城市的答案
ll ans=0;
for(re int i=1;i<=n;i++)
if(val[i])
ans+=len[i];
cout<<ans<<endl;
return 0;
}

CF1336 Linova and Kingdom的更多相关文章

  1. Codeforces Round #635C Linova and Kingdom 思维

    Linova and Kingdom 题意 现在有一颗n个节点的树,每个节点是一个城市,现在要选出k个城市作为工业城市,其他城市作为旅游城市,现在每个工业城市要派出一名特使前往根节点,每个特使的幸福度 ...

  2. Codeforces Round #635 C. Linova and Kingdom

    传送门:C. Linova and Kingdom 题意:给你一棵树,要求对k个结点涂色,然后统计每个未涂色结点到根结点的路径上未涂色结点的和,求和最大能为多少 题解:对着样例画几遍,然后贪心发现,最 ...

  3. Linova and Kingdom(树型-贪心)

    题目大意:给定一棵树,1为首都(首都可以是工业城市也可以是旅游城市),一共有n个点. 其中要选出k个工业城市,每个工业城市出一个代表去首都,其快乐值是其途径旅游城市(非工业)的个数 求所有快乐值相加的 ...

  4. Codeforces 1337C Linova and Kingdom

    题意 给你一颗有根树,你要选择\(k\)个点,最大化\(\sum_{i \in S} val_i\),其中\(S\)是被选点的集合,\(val_i\)等于节点\(i\)到根的路径上未被选择点的个数. ...

  5. Codeforces Round #635 (Div. 2) 题解

    渭城朝雨浥轻尘,客舍青青柳色新. 劝君更尽一杯酒,西出阳关无故人.--王维 A. Ichihime and Triangle 网址:https://codeforces.com/contest/133 ...

  6. Codeforces Round #635 (Div. 2)部分(A~E)题解

    虽然打的是div1,但最后半小时完全处于挂机状态,不会做1C,只有个 \(O(n^3)\) 的想法,水了水论坛,甚至看了一下div2的AB,所以干脆顺便写个div2的题解吧,内容看上去还丰富一些(X) ...

  7. Codeforces Round #635 (Div. 2)

    Contest Info Practice Link Solved A B C D E F 4/6 O O Ø  Ø     O 在比赛中通过 Ø 赛后通过 ! 尝试了但是失败了 - 没有尝试 Sol ...

  8. Codeforces Round #635 (Div. 1)

    传送门 A. Linova and Kingdom 题意: 给定一颗以\(1\)为根的树,现在要选定\(k\)个结点为黑点,一个黑点的贡献为从他出发到根节点经过的白点数量. 问黑点贡献总和最大为多少. ...

  9. Constructing Roads In JGShining's Kingdom(HDU1025)(LCS序列的变行)

    Constructing Roads In JGShining's Kingdom  HDU1025 题目主要理解要用LCS进行求解! 并且一般的求法会超时!!要用二分!!! 最后蛋疼的是输出格式的注 ...

随机推荐

  1. linux系统修改不成功/无法修改密码

    1.问题描述 新上架的60台浪潮服务器使用某带外装机平台进行统一安装,安装完成后修改用户密码时统一无法修改,使用root账户无法修改其他用户密码,自身根密码也无法修改成功 2.排查问题 因带外装机平台 ...

  2. Tomcat学习小记(二)

    1.Tomcat源码入口 生命周期统一管理接口:LifeCycle 实现LifeCycle接口的类:(idea快捷键:Ctrl+h) 多个组件共同实现LifeCycle接口 Tomcat启动入口分析: ...

  3. Centos-挂载和卸载分区-mount

    mount 挂载和卸载指定的分区 相关选项 -a 加载文件 /etc/fstab中指定的所有设备 -n 不降加载信息记录在 /etc/mtab文件中 -r 只读方式加载设备 -w   可读可写价值设备 ...

  4. Go 数组&切片

    数组相关 在Go语言中,数组是一种容器相关的数据类型,用于存放多种相同类型的数据. 数组定义 在定义数组时,必须定义数组的类型以及长度,数组一经定义不可进行改变. 同时,数组的长度是按照元素个数进行统 ...

  5. osgEarth使用笔记1——显示一个数字地球

    目录 1. 概述 2. 实现 2.1. 三维显示 2.2. 二维显示 1. 概述 osgEarth支持.earth格式的文件,里面保存了数字地球相关信息的配置XML,只需要读取这个配置文件,就可以直接 ...

  6. C\C++中计时、延时函数

    转载:https://blog.csdn.net/keith_bb/article/details/53055380 C\C++标准库中提供了两种计时函数clock()和time().其用法如下:(1 ...

  7. matlab中fopen 打开文件或获得有关打开文件的信息

    参考:https://ww2.mathworks.cn/help/matlab/ref/fopen.html?searchHighlight=fopen&s_tid=doc_srchtitle ...

  8. 结合实体框架(代码优先)、工作单元测试、Web API、ASP. net等,以存储库设计模式开发示例项目。NET MVC 5和引导

    介绍 这篇文章将帮助你理解在库模式.实体框架.Web API.SQL Server 2012.ASP中的工作单元测试的帮助下设计一个项目.净MVC应用程序.我们正在开发一个图书实体和作者专用的样例图书 ...

  9. C# 软件开机启动

    如果需要查看更多文章,请微信搜索公众号 csharp编程大全,需要进C#交流群群请加微信z438679770,备注进群, 我邀请你进群! ! !---------------------------- ...

  10. protoc-c 阅读笔记

    以前和山哥做过类似的,最近想起来,抽空又看了下 protoc-c. 山哥做的报文流向: rpc -> lydtree -> motree -> struct 涉及的细节很多 1) l ...