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. django(新增model)No migrations to apply.

    django 1.8版本,在models下新建一个class,无法在数据库创建新表的问题: - models.py class HostPwd(models.Model): hostname = mo ...

  2. Go单元测试注意事项及测试单个方法和整个文件的命令

    Go程序开发过程中免不了要对所写的单个业务方法进行单元测试,Go提供了 "testing" 包可以实现单元测试用例的编写,不过想要正确编写单元测试需要注意以下三点: Go文件名必须 ...

  3. 笨办法学Python - 习题5: More Variables and Printing

    1.习题 5: 更多的变量和打印 学习目标:了解用户输入方法,明白pthon2和Python3之间的用户输入的区别.了解格式化字符串(format string)的概念,学会如何创建包含变量内容的字符 ...

  4. 在Gulp中使用BrowserSync

    博客已迁移至http://zlwis.me. 很早就听说过BrowserSync,也看过一些相关文章,可就是没用过.之前一直在用Gulp开发项目,每次编写完Sass后还要用按F5刷新页面看效果,想想也 ...

  5. 20145214《网络攻防》逆向及Bof基础实践

    20145214<网络攻防>逆向及Bof基础实践 实践说明 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何 ...

  6. 每日Scrum(10)

    今天我们小组整合了下我们所编辑的程序,然后在界面上进行了修改和少部分的完善,现在就等着下午的验收了 任务展板 燃尽图如下:

  7. Task 7 买书最低价格问题

    任务: 书店针对<哈利波特>系列书籍进行促销活动,一共5卷,用编号0.1.2.3.4表示,单独一卷售价8元, 具体折扣如下所示: 本数    折扣 2         5% 3       ...

  8. b4

    吴晓晖(组长) 过去两天完成了哪些任务 昨天FloatingActionButton和权限获取调整 今天复习,没写东西,晚点有空了写 展示GitHub当日代码/文档签入记录 接下来的计划 推荐算法 还 ...

  9. iOS开发短信验证码封装 方便好用

    ---恢复内容开始--- 1.RootViewControler//  Copyright © 2016年 Chason. All rights reserved.// #import "V ...

  10. 复利计算测试(C语言)

    对我们和复利计算程序,写单元测试. 有哪些场景? 期待的返回值 写测试程序. 运行测试. 测试模块 测试输入 预期结果 运行结果 bug跟踪 计算终值 (本金,年限,利率) 终值     1 (100 ...