【CF1187E】Tree Painting
2024-09-05 14:04:10
题目大意:给定一棵 N 个点的树,初始全是白点。要求你做 N 步操作,每一次选定一个与一个黑点相隔一条边的白点,将它染成黑点,然后获得该白点被染色前所在的白色联通块大小的权值。第一次操作可以任意选点,求可获得的最大权值。
题解:对于答案仅由起始点决定的 dp 采用换根法。
发现对于两个相邻的染了黑色的点来说,这两个点染色的先后顺序会对答案产生影响,但是不会对其他点产生影响。同时,可以发现该问题一旦选定了初始点,无论怎样进行染色,答案均相同。因此,考虑采用换根法,需要计算出相邻两个点先后顺序对答案的影响,根据第一个性质,可知仅需要计算第一次两个点对答案的影响即可。画图可知,相邻两点对答案贡献的差值为 \(n-2*sz[v]\)。
代码如下
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int maxn=2e5+10;
typedef long long LL;
int n,sz[maxn];
vector<int> G[maxn];
LL f[maxn],ans;
void dfs1(int u,int fa){
sz[u]=1;
for(auto v:G[u]){
if(v==fa)continue;
dfs1(v,u);
sz[u]+=sz[v];
}
ans+=sz[u];
}
void dfs2(int u,int fa){
ans=max(ans,f[u]);
for(auto v:G[u]){
if(v==fa)continue;
f[v]=f[u]+n-2*sz[v];
dfs2(v,u);
}
}
void read_and_parse(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
G[x].pb(y),G[y].pb(x);
}
}
void solve(){
dfs1(1,0);
f[1]=ans;
dfs2(1,0);
printf("%lld\n",ans);
}
int main(){
read_and_parse();
solve();
return 0;
}
最新文章
- CDH5.4.5运行多字符分割记录
- Andrew Ng机器学习公开课笔记 -- 支持向量机
- Oracle实例和Oracle数据库(Oracle体系结构)
- 实战RPM包制作
- svg text文字居中
- java--九九乘法表
- 搭建rtmp直播流服务之1:使用nginx搭建rtmp直播流服务器(nginx-rtmp模块的安装以及rtmp直播流配置)
- 前端基础之JavaScript
- python爬虫动态html selenium.webdriver
- 使用 Nexus Repository Manager 搭建私有docker仓库
- SQL kaggle learn with as excercise
- Spring详解
- APP微信支付报错《商户号该产品权限未开通,请前往商户平台>;产品中心检查后重试》
- Windows 远程栈溢出挖掘与利用
- [转]Visual Studio 2010 中安装Qt 5.1
- maven聚合工程tomcat插件启动没有 Starting ProtocolHandler [";http-bio-8081";]
- 【BZOJ4817】【SDOI2017】树点染色
- php的常量
- LeetCode 3Sum (Two pointers)
- jsonp跨域远离