Description

给定一棵 \(n\) 个节点的树,点有点权 \(a_u\),可能为负。现在请你在树上找出 \(k~(1~\leq~k~\leq~n)\) 个不相交集合,使得每个集合中的每对点都可以通过本集合中的点互相到达,假设选出的 \(k\) 个集合的并集为 \(s\),要求最大化:

\[\frac{\sum_{u \in s} a_u}{k}
\]

如果有多解请输出 \(k\) 最大的解

Input

第一行是节点个数 \(n\)。

下面一行 \(n\) 个数代表点权

下面 \(n - 1\) 行描述这棵树

Output

输出一行两个整数,分别是选出的点权和以及 \(k\)

不约分

Solution

结论:在不限元素个数时,要求选出元素的平均值最大,则最优解一定为只选择元素值最大的元素。如果有多个元素的值最大,选择个数对答案无影响。

证明:数学归纳法,先将元素按照权值降序排序。当只选择 \(1\) 个元素的时候,显然选择第一个元素最优。考虑已经选了 \(k\) 个元素,现在要决定是否选 \(k + 1\) 个元素。由于是降序排序的,则这个元素的权值显然不大于前面所有元素的平均值。设前面所有元素的平均值为 \(a\),第 \(k + 1\) 个元素的权值为 \(w\),则选择该元素后的平均值为 \(\frac{ak + w}{k + 1}\) 。要判断它和原平均值 \(a\) 的关系,则对它们做差,记 \(\delta~=~\frac{ak + w}{k + 1} - a\)

\[\delta~=~\frac{ak}{k + 1} + \frac{w}{k + 1}- \frac{a(k + 1)}{k + 1}~=~\frac{w}{k + 1} - \frac{a}{k + 1}~=~\frac{w - a}{k + 1}
\]

前面已经论证 \(w~\leq~a\),于是 \(\delta~\leq~0\)。当且仅当 \(w~=~a\) 即前 \(k + 1\) 个元素权值相同时,等号成立。证毕。

于是根据这个结论,问题就被转化成了:求一个符合要求的集合使得这个集合的权值和尽可能大,然后统计有多少个这样的不想交的集合。

第一问显然可以直接树形DP,设 \(f_u\) 为 \(u\) 的子树中必选 \(u\) 的集合的最大权值,则有:

\[f_u~=~\sum_{to} \max(f_{to}, 0)
\]

于是就可以求出最大的权值了。考虑统计答案时,由于要求的是不相交的集合,所以我们每将一个集合加入贡献以后再将这个集合删掉,一边统计答案一遍DP就可以了。

Code

#include <cstdio>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#define putchar(o) \
puts("I am a cheater!")
#endif
#define rg register
#define ci const int
#define cl const long long typedef long long int ll; namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
} template <typename T>
inline void qr(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
} template <typename T>
inline void ReadDb(T &x) {
rg char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch = IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = x * 10 + (ch ^ 48), ch = IPT::GetChar();
if (ch == '.') {
ch = IPT::GetChar();
double base = 1;
while ((ch >= '0') && (ch <= '9')) x += (ch ^ 48) * ((base *= 0.1)), ch = IPT::GetChar();
}
if (lst == '-') x = -x;
} namespace OPT {
char buf[120];
} template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
rg int top=0;
do {OPT::buf[++top] = char(x % 10 + '0');} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
} const int maxn = 300010;
const int maxm = 600010; struct Edge {
int to;
Edge *nxt;
};
Edge edge[maxm], *hd[maxn];int ecnt;
inline void cont(ci from, ci to) {
Edge &e = edge[++ecnt];
e.to = to; e.nxt = hd[from]; hd[from] = &e;
} int n, cnt;
ll ans = -(1ll << 62);
ll MU[maxn], frog[maxn]; void reading();
void dfs(ci, ci, ci); int main() {
freopen("1.in", "r", stdin);
qr(n);
for (rg int i = 1; i <= n; ++i) qr(MU[i]);
reading();
dfs(1, 0, 1); dfs(1, 0, 0);
qw(ans * cnt, ' ', true); qw(cnt, '\n', true);
return 0;
} void reading() {
int a, b;
for (rg int i = 1; i < n; ++i) {
a = b = 0; qr(a); qr(b);
cont(a, b); cont(b, a);
}
} void dfs(ci u, ci fa, ci op) {
frog[u] = MU[u];
for (Edge *e = hd[u]; e; e = e->nxt) {
int &to = e->to;
if (to == fa) continue;
dfs(to, u, op);
if (frog[to] > 0) frog[u] += frog[to];
}
if (op) ans = std::max(ans, frog[u]);
else if (frog[u] == ans) ++cnt, frog[u] = -(1ll << 60);
}

Summary

选择任意个元素使得平均值最大时,只选择最大的就好啦

【数学/贪心/DP】【CF1088E】 Ehab and a component choosing problem的更多相关文章

  1. cf1088E Ehab and a component choosing problem (树形dp)

    题意(考试时看错了对着样例wa了好久..):从树上选k个连通块,使得权值的平均值最大的基础上,选的块数最多 如果不考虑块数最多的限制,肯定是只选一个权值最大的块是最好的 然后只要看这个权值最大的块有多 ...

  2. Codeforces 1088E Ehab and a component choosing problem

    Ehab and a component choosing problem 如果有多个连接件那么这几个连接件一定是一样大的, 所以我们先找到值最大的连通块这个肯定是分数的答案. dp[ i ]表示对于 ...

  3. Codeforces Round #525 (Div. 2)E. Ehab and a component choosing problem

    E. Ehab and a component choosing problem 题目链接:https://codeforces.com/contest/1088/problem/E 题意: 给出一个 ...

  4. Codeforces Round #525 (Div. 2) E. Ehab and a component choosing problem 数学

    题意:给出树 求最大的sigma(a)/k k是选取的联通快个数   联通快不相交 思路: 这题和1个序列求最大的连续a 的平均值  这里先要满足最大平均值  而首先要满足最大  也就是一个数的时候可 ...

  5. cfE. Ehab and a component choosing problem(贪心)

    题意 题目链接 给出一棵树,每个节点有权值,选出\(k\)个联通块,最大化 \[\frac{\sum_{i \in S} a_i}{k}\] Sol 结论:选出的\(k\)个联通块的大小是一样的且都等 ...

  6. Codeforces Round #525 E - Ehab and a component choosing problem

    题目大意: 在一棵树中 选出k个联通块 使得 这k个联通块的点权总和 / k 最大 并且这k个联通块不相互覆盖(即一个点只能属于一个联通块) 如果有多种方案,找到k最大的那种 给定n 有n个点 给定n ...

  7. 【BZOJ-3174】拯救小矮人 贪心 + DP

    3174: [Tjoi2013]拯救小矮人 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 686  Solved: 357[Submit][Status ...

  8. BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP

    BZOJ_3174_[Tjoi2013]拯救小矮人_贪心+DP Description 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决定搭一个人梯.即:一个小矮人站在另一小矮人的 肩膀 ...

  9. 洛谷P4823 拯救小矮人 [TJOI2013] 贪心+dp

    正解:贪心+dp 解题报告: 传送门! 我以前好像碰到过这题的说,,,有可能是做过类似的题qwq? 首先考虑这种显然是dp?就f[i][j]:决策到了地i个人,跑了j个的最大高度,不断更新j的上限就得 ...

随机推荐

  1. 【机器学习】无监督学习Autoencoder和VAE

    众所周知,机器学习的训练数据之所以非常昂贵,是因为需要大量人工标注数据. autoencoder可以输入数据和输出数据维度相同,这样测试数据匹配时和训练数据的输出端直接匹配,从而实现无监督训练的效果. ...

  2. API验证

    API验证说明 API验证: a. 发令牌: 静态 PS: 隐患 key被别人获取 b. 动态令牌 PS: (问题越严重)用户生成的每个令牌被黑客获取到,都会破解 c. 高级版本 PS: 黑客网速快, ...

  3. 作业1MathExam

    自己取一个大气又可爱的标题 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 720 1000 ...

  4. 项目Beta冲刺(团队)总结

    团队成员及分工 姓名 学号 分工 陈家权 031502107 前端(消息模块) 赖晓连 031502118 前端(问答模块) 雷晶 031502119 服务器 林巧娜 031502125 前端(首页模 ...

  5. Leetcode题库——9.回文数

    @author: ZZQ @software: PyCharm @file: HuiWenShu.py @time: 2018/9/16 16:51 要求:判断一个整数是否是回文数.回文数是指正序(从 ...

  6. C语言:一个能自动生成小学四则运算题目的程序

    完成这个程序,半个小时内完成了,这个程序,可以自动生成小学简易的四则运算,提供菜单让用户选择,然后判断加减乘除,判断答对答错的题目个数,用户同时也可以重新选择继续答题或重新选择或退出程序. 源程序: ...

  7. java中方法传入参数时:值传递还是址传递?

    JAVA中的数据类型有两大类型: ① 基本数据类型:逻辑型(boolean).文本型(char).整数型(byte.short.int.long).浮点型(float.double) ② 引用数据类型 ...

  8. Beta阶段团队项目开发篇章2

    例会时间: 2016.12.4 例会照片 个人工作 上阶段任务验收: 组员任务都已完成. 任务分配 组员 任务内容 韩慧敏 对调查问卷的结果进行分析和总结,确定Beta阶段各任务的优先级,撰写相关博客 ...

  9. 1014 C语言文法定义

    <程序>→<外部声明>|<程序><外部声明><外部声明>→<函数定义>|<声明><函数定义>→<数 ...

  10. 面试问题总结二(技术能力-PHP)----Ⅱ

    20.支付功能的实现? 答:在线支付一般来说有两种实现方式,一种是调用各个银行提供的接口,另一种是使用第三方集成好的支付功能,两种方式各有优劣.对于第三方支付来说会需要提交企业5证来验证,还会有部分手 ...