比赛的时候看到题意没多想就放弃了。结果最后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+思维的更多相关文章

  1. Codeforces 1153D 树形DP

    题意:有一个游戏,规则如下:每个点有一个标号,为max或min, max是指这个点的值是所有子节点中值最大的那一个,min同理.问如何给这颗树的叶子节点赋值,可以让这棵树的根节点值最大. 思路:很明显 ...

  2. CF482D Random Function and Tree 树形DP + 思维 + 神题

    Code: #include<bits/stdc++.h> #define ull unsigned long long #define MOD 1000000007 #define ll ...

  3. Codeforces 1179D 树形DP 斜率优化

    题意:给你一颗树,你可以在树上添加一条边,问添加一条边之后的简单路径最多有多少条?简单路径是指路径中的点只没有重复. 思路:添加一条边之后,树变成了基环树.容易发现,以基环上的点为根的子树的点中的简单 ...

  4. CodeForces - 337D 树形dp

    题意:一颗树上有且仅有一只恶魔,恶魔会污染距离它小于等于d的点,现在已经知道被污染的m个点,问恶魔在的可能结点的数量. 容易想到,要是一个点到(距离最远的两个点)的距离都小于等于d,那么这个点就有可能 ...

  5. cf1153D 树形dp+思维

    一千八的题也不会做了呜呜呜 size[u]表示结点u下的叶子结点, 思维:可以想到一个子树对其父亲会有一个消耗值 考虑一个点如果是max,那么其最大值可以是size[u]-p,p是消耗值最小的子树 一 ...

  6. CodeForces 219D 树形DP

    D. Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes i ...

  7. codeforces 337D 树形DP Book of Evil

    原题直通车:codeforces 337D Book of Evil 题意:一棵n个结点的树上可能存在一个Evil,Evil危险范围为d,即当某个点与它的距离x<=d时,那么x是危险的. 现已知 ...

  8. codeforces 1140D(区间dp/思维题)

    D. Minimum Triangulation time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  9. Up and Down the Tree CodeForces - 1065F (树形dp)

    链接 题目大意:给定$n$结点树, 假设当前在结点$v$, 有两种操作 $(1)$移动到$v$的子树内任意一个叶子上 $(2)$若$v$为叶子, 可以移动到距离$v$不超过$k$的祖先上 初始在结点$ ...

随机推荐

  1. react里面 react-router4 跳转

    在react里面跳转的时候,一般可以用 <Link to='/tradeList' /> 但是我们在运用组件组合的时候经常会通过传参去判断,如果props传过来是参数,如果有link进行跳 ...

  2. 1.6 NBU Catalog备份还原

    用户的数据保存到了磁盘或者磁带中,并且是安全的,NBU所在的机器还有可能发生故障,需要重新安装或者将NBU部署到其他的机器中继续使用. 在这种情况下,如何让NBU知道用户已经存在的备份策略和存储单元配 ...

  3. U盘装CentOS6.4

    1.打开UltraISO,依次点击“文件”>“打开”,选择“CentOS-6.4-i386-bin-DVD1.iso”文件. 2.“启动”>“写入硬盘映像”,在“硬盘驱动器选择u盘”,写入 ...

  4. ibator自动代码生成

    首先,强烈推荐一篇文章,介绍的特详细 http://www.iteye.com/topic/821983 1. 插件安装 http://blog.csdn.net/rchm8519/article/d ...

  5. 前端jQuery之文档操作

    1.文档操作内部插入 A.append(B) 吧B添加到A的后面 A.appendTo(B) 吧A添加到B的后面 A.prepend(B) 吧B添加到A的前面 A.prependTo(B) 吧A添加到 ...

  6. lambda函数,内置map()函数及filter()函数

    8.1 lambda函数 作用及意义:  1.没必要专门定义函数,给函数起名,起到精简的效果  2.简化代码的可读性 def ds(x): return 2 * x + 1 ds(5) ---11 g ...

  7. SAP BI 常用TCODE

    S.No Tcode Description 1 RSA1 Administrator Work Bench 2 RSA11 Calling up AWB with the IC tree 3 RSA ...

  8. Anaconda下安装 TensorFlow 和 keras 以及连接pycharm

    首先在官网下载Anaconda https://www.anaconda.com/download/ 安装时注意 勾选第一个,增加环境变量 安装好后再windows界面打开Anaconda Promp ...

  9. mongodb多个查询语句

    db.getCollection('costitems').find({"created":{"$gte":ISODate("2019-01-02T0 ...

  10. python之doctest的用法

    doctest是python自带的一个模块,你可以把它叫做“文档测试”(doctest)模块. doctest的使用有两种方式:一个是嵌入到python源中.另一个是放到一个独立文件. doctest ...