Codeforces 1088E 树形dp+思维
比赛的时候看到题意没多想就放弃了。结果最后D也没做出来,还掉分了,所以还是题目做的太少,人太菜。
回到正题:
题意:一棵树,点带权值,然后求k个子连通块,使得k个连通块内所有的点权值相加作为分子除以k的值最大,如果这样的最大值有多个,就最大化k。
赛后看了看别人的代码仔细想了一想,还是挺容易的。
首先将树分为若干个连通块,考虑一个权值求和最大的连通块,设该最大值为sum,那么其他所有的连通块,权值求和都不可能比当前的连通块大。
在不考虑最大化k的情况下,就没有必要再将其他的连通块加进来(因为如果加进来,(sum+加进来的连通块权值和)/(k+1)<=sum/k,就必定成立,其实本质上就是求一个均值,加比当前值还要小的值会使得这个均值变小),所以答案就是sum。
现在要考虑答案相同时,最大化k,那么本质上只要将其他的权值和等同于当前最大权值和的连通块加进来就好,这样分子就变成了sum*k,k个连通块。
经队友赛后一提醒,其实实际上这就是一个最大连续和的树上版本,树形dp一下就出来了。
设dp[i]表示以i为根的子树,包含i在内的权值求和最大的连通块的权值和。
状态转移就有两种选择,枚举他的子树,那么:1.连这棵子树;2.不连这颗子树。
易得状态转移方程:
dp[i]+=max(dp[j],0) (j为i的子节点)(类似于线性结构上的最大连续和)
然后获取所有dp中的最大值,就是sum。
之后发现一个问题,如何区别以下情况:
存在多个连通块权值和最大,但其中某个连通块是另一个连通块的子图。
比方说以下这组数据:
4
0 1 1 1
1 2
2 3
2 4
如果只是朴素计数(计算有多少个结点的dp值等于sum),那么答案将会是2(dp[1]==dp[2]==ans==3),而实际答案应该是1,这是因为以2为根的子树被包含在以1为根的子树中。
为了解决这个问题,考虑再做一次树形dp,每次dfs退出该结点时如果当前结点的dp值等于sum,就k++,然后dp值改为0,就将该结点与父节点断开了,最后答案就是sum*k,k个连通块。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=;
int cnt;
int head[maxn];
struct edge
{
int to,nxt;
}e[*maxn];
ll a[maxn];
void inline addedge(int u,int v)
{
e[++cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
ll dp[maxn];
ll ans=-1e18,k;
void dfs(int fa,int u)
{
dp[u]=a[u];
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs(u,v);
dp[u]+=max(dp[v],0LL);
}
ans=max(ans,dp[u]);
}
void dfs2(int fa,int u)
{
dp[u]=a[u];
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs2(u,v);
dp[u]+=max(dp[v],0LL);
}
if(dp[u]==ans)
{
k++;
dp[u]=;
}
}
int main()
{
#ifdef local
//freopen("in.txt","r",stdin);
#endif // local
ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=;i<=n;i++)
cin>>a[i];
for(int i=;i<=n-;i++)
{
int x,y;
cin>>x>>y;
addedge(x,y);
addedge(y,x);
}
dfs(-,);
dfs2(-,);
cout<<ans*k<<" "<<k<<endl;
}
Codeforces 1088E 树形dp+思维的更多相关文章
- Codeforces 1153D 树形DP
题意:有一个游戏,规则如下:每个点有一个标号,为max或min, max是指这个点的值是所有子节点中值最大的那一个,min同理.问如何给这颗树的叶子节点赋值,可以让这棵树的根节点值最大. 思路:很明显 ...
- CF482D Random Function and Tree 树形DP + 思维 + 神题
Code: #include<bits/stdc++.h> #define ull unsigned long long #define MOD 1000000007 #define ll ...
- Codeforces 1179D 树形DP 斜率优化
题意:给你一颗树,你可以在树上添加一条边,问添加一条边之后的简单路径最多有多少条?简单路径是指路径中的点只没有重复. 思路:添加一条边之后,树变成了基环树.容易发现,以基环上的点为根的子树的点中的简单 ...
- CodeForces - 337D 树形dp
题意:一颗树上有且仅有一只恶魔,恶魔会污染距离它小于等于d的点,现在已经知道被污染的m个点,问恶魔在的可能结点的数量. 容易想到,要是一个点到(距离最远的两个点)的距离都小于等于d,那么这个点就有可能 ...
- cf1153D 树形dp+思维
一千八的题也不会做了呜呜呜 size[u]表示结点u下的叶子结点, 思维:可以想到一个子树对其父亲会有一个消耗值 考虑一个点如果是max,那么其最大值可以是size[u]-p,p是消耗值最小的子树 一 ...
- CodeForces 219D 树形DP
D. Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes i ...
- codeforces 337D 树形DP Book of Evil
原题直通车:codeforces 337D Book of Evil 题意:一棵n个结点的树上可能存在一个Evil,Evil危险范围为d,即当某个点与它的距离x<=d时,那么x是危险的. 现已知 ...
- codeforces 1140D(区间dp/思维题)
D. Minimum Triangulation time limit per test 2 seconds memory limit per test 256 megabytes input sta ...
- Up and Down the Tree CodeForces - 1065F (树形dp)
链接 题目大意:给定$n$结点树, 假设当前在结点$v$, 有两种操作 $(1)$移动到$v$的子树内任意一个叶子上 $(2)$若$v$为叶子, 可以移动到距离$v$不超过$k$的祖先上 初始在结点$ ...
随机推荐
- Eclipse快捷键功能
转载一篇另人写的:https://blog.csdn.net/qq_30617755/article/details/50781003 Eclipse的编辑功能非常强大,掌握了Eclipse快捷键功能 ...
- 2018.9.6 Java常考知识点总结
一 Java中的值传递和引用传递(非常重要) 首先要明确的是:"对象传递(数组.类.接口)是引用传递,原始类型数据(整型.浮点型.字符型.布尔型)传递是值传递." 那么什么是值传递 ...
- js中关于假值和空数组的总结
先上x==y运算符的算法细节: 如果x不是正常值(比如抛出一个错误),中断执行. 如果y不是正常值,中断执行. 如果Type(x)与Type(y)相同,执行严格相等运算x === y. 如果x是nul ...
- Leetcode463. Island Perimeter
题目 给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域. 网格中的格子水平和垂直方向相连(对角线方向不相连).整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表 ...
- Java - 静态内部类
Java语言允许在类中再定义类,这种在其它类内部定义的类就叫内部类.内部类又分为:常规内部类.局部内部类.匿名内部类和静态嵌套类四种. 1.静态内部类定义 静态内部类,定义在类中,任何方法外,用sta ...
- DB设计工具——dbschema
Preface I've got a db design job about meeting room booking system last week.There're many s ...
- GNU 关闭 MMU 和 Icache 和 Dcache
1. cp15 寄存器 disable Icache 和 Dcache . disable_MMU: MCR p15,0,r0,c7,c7,0 MRC p15,0,r0,c1,c0,0 bic r ...
- JAVA / MySql 编程—— 第三章 高级查询(一)
1. 修改表: (1)修改表名语法: ALTER TABLE <旧表名> RENAME [ TO ] <新表名>: 注意:其中[TO]为可选参数,使用与否不影响结 ...
- sql常用函数instr()和substr()
Decode decode(条件,值1,翻译值1,值2,翻译值2,...,缺省值) 该函数与程序中的 If...else if...else 意义一样 NVL 格式:NVL( string1, rep ...
- 再次写给VC++ Windows开发者
距离我的上一篇文章--写给VC++ Windows开发的初学者已经4年多时间过去了,感慨于时光如梭之余,更感慨于这么多年来(从1998年我初学VC 算起吧)到如今其实我仍然还只是个初学者而已.看看之前 ...