首页 > 其他分享 >[HAOI2015] 树上染色

[HAOI2015] 树上染色

时间:2024-11-25 21:13:49浏览次数:10  
标签:size1 siz long HAOI2015 为根 染色 树上 dp size

题目链接

树形DP

简要题意

\(n\) 个点的树,其中 \(k\) 个点染黑色,\(n-k\) 个点染白色,求黑点两两距离之和加白点两两之和的最大值。

思路

我们首先考虑如果 \(k=0\)时,答案应该怎么算,此时显然是 \(\sum_{i=1}^n\sum_{j=i+1}^n dis(i,j)\)。

然后我们考虑如何在 \(O(n)\) 的时间复杂度内求出答案,明显我们可以将每条边的贡献拆开来算。
而经过边 \(u\to v\) 的次数明显为 \(size_v*(n-size_v)\),很好理解,就是因为子树内每个点要到底子树外的点需要经过这条边。

这启发我们如何算黑白点的贡献,设 \(size1_x\) 表示以 \(x\) 为根的子树内黑点的数量,\(size2_x\) 表示以 \(x\) 为根的子树内白点的数量。
那么经过边 \(u\to v\) 的次数就是 \(size1_v*(k-size1_v)+size2_v*(n-k-size2_v)\)。此时就很好做了,设 \(dp_{i,j}\) 表示以 \(i\) 为根的子树内选 \(j\) 个黑点的边的最大贡献和。

那么对于边 \(u\to v\) 有

\[dp_{u,i+j}=\max_{i=1,j=1}^{k,i+j\le k} \{dp_{u,i}+dp_{v,j}+j*(k-j)*w_{u\to v}+(size_v-j)*(n-k-size_v+j)*w_{u\to v}\} \]

\(Code\)

/*

*/
#include <bits/stdc++.h>
using namespace std;
inline long long read(){
    long long x=0,w=0;char c=0;
    while(!isdigit(c)) {w|=c=='-';c=getchar();}
    while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return w?-x:x;
}
long long n,k;
struct edge{
	int to,nex;
	long long w;
}e[4050];
int h[2050],cnt;
inline void add(int x,int y,int w){
	e[++cnt]={y,h[x],w};
	h[x]=cnt;
}
long long dis[2050];
long long dp[2050][2050],siz[2050],f[2050];
void dfs(int x,int fa){
	siz[x]=1;
	for(int i=h[x];i;i=e[i].nex){
		int v=e[i].to;
		if(v==fa){
			continue;
		}
		dis[v]=dis[x]+e[i].w;
		dfs(v,x);
		for(int i=0;i<=k;i++){
			f[i]=0;
		}
		for(int l=0;l<=min(siz[x],k);l++){
			for(int j=0;j<=min(siz[v],k);j++){
				if(l+j>k){
					break;
				}
				f[l+j]=max(f[l+j],dp[x][l]+dp[v][j]+e[i].w*j*(k-j)+e[i].w*(siz[v]-j)*(n-k-siz[v]+j));
			}
		}
		siz[x]+=siz[v];
		for(int j=0;j<=min(siz[x],k);j++){
			dp[x][j]=f[j];
		}
	}
}
int main(){ 
	n=read();
	k=read();
	for(int i=1,x,y,z;i<n;i++){
		x=read();
		y=read();
		z=read();
		add(x,y,z);
		add(y,x,z);
	}
	dfs(1,0);
	printf("%lld",dp[1][k]);
	return 0; 
}
/*

*/

标签:size1,siz,long,HAOI2015,为根,染色,树上,dp,size
From: https://www.cnblogs.com/pjt-camellia/p/18568738

相关文章

  • 线段树上二分
    线段树上二分费劲学的,得单领出来说说。网上有没有多少详细文章,有例题。线段树的奇幻科技——线段树上二分-Mercury_City-博客园(cnblogs.com)这篇博客讲的好,但仍不详细。不是二分+线段树,是直接利用线段树去二分查找。从而把\(O(\log^2n)\)变为\(O(\logn)\)。基本原......
  • JCO发表加州大学团队最新医学AI研究,从常规HE染色切片预测同源重组缺陷和铂类药物反应|
    小罗碎碎念这篇文章是关于一项名为DeepHRD的深度学习平台的研究,该平台能够从常规的苏木精-伊红(H&E)染色组织切片中预测同源重组缺陷(HRD)和铂类药物反应。作者角色姓名单位第一作者ErikN.Bergstrom加州大学圣地亚哥分校Moores癌症中心通讯作者LudmilB.Alexandrov加州......
  • 二分图的判定-染色法
    二分图如果一张无向图的N个节点可以分成A.B两个不相交的非空集合,并且同一集合内的点之间没有边相连,那么称该无向图为二分图(BipartiteGraph)。定理:二分图不存在奇环(长度为奇数的环)。因为每一条边都是从一个集合走到另一个集合,只有走偶数次才可能回到同一个集合。染色......
  • 教授(优青)团队一站式指导:专业实验设计、数据分析、SCI论文辅助。基因表达分析、转录因
    可高通量检测组蛋白不同修饰在基因组上的位点;可用于模式物种和非模式物种的研究,无需特异性抗体;完整的DAP-seq解决方案。DAP-seq可高通量检测转录因子或DNA结合蛋白在基因组上的结合位点;可用于模式物种和非模式物种的研究,无需特异性抗体;完整的基因功能分析解决方案......
  • 染色法判定二分图
    给定一个 nn 个点 mm 条边的无向图,图中可能存在重边和自环。请你判断这个图是否是二分图。输入格式第一行包含两个整数 nn 和 mm。接下来 mm 行,每行包含两个整数 uu 和 vv,表示点 uu 和点 vv 之间存在一条边。输出格式如果给定图是二分图,则输出 Yes,否则......
  • 树上差分+lca 黑暗的锁链
    //**太久不写了,感觉很难受。。。比赛最近打得也不好,课内任务又重,还要忙着做项目。何去何从。今天又写了一题,用了树上差分的知识。下面来整理整理。1.首先让我们学一下lca(最小公共父节点) 我用的是倍增来求的。总共其实就是两步:dfs打ST表预处理每个点的上面节点 lca求两......
  • 2023年全国高中数学联合竞赛A卷加试P3:组合极值、染色
    题目求具有下述性质的最小正整数$k$:若将$1,2,\cdots,k$中的每个数任意染为红色或者蓝色,则或者存在$9$个不同的红色的数$x_1,x_2,\cdots,x_9$满足$x_1+x_2+\cdots+x_8<x_9,$或者存在$10$个互不相同的蓝色的数$y_1,y_2,\cdots,y_{10}$满足$y_1+y_2+\cdots+y_9<y_{10}.$解......
  • P4551 最长异或路径(树上前缀异或01-trie)
    #include<bits/stdc++.h>usingnamespacestd;#definexfirst#defineysecondtypedefpair<int,int>PII;typedeflonglongll;typedefunsignedlonglongull;typedefunsignedintuint;typedefvector<string>VS;typedefvector<int>......
  • 树上圆理论
    设\(f(u,r)=\{v|dis(u,v)\ler\}\),可以将其视作以\(u\)为圆心,\(r\)为半径的圆。有若干与欧几里得空间的圆相同的性质。设点集\(S\)的直径长度为\(d(S)\),中点为\(m(S)\),设\(c(S)=f(m(S),\dfrac{d(S)}{2})\),可以视作\(S\)的最小覆盖圆。Lemma:若点集\(S......
  • 洛谷P3128 [USACO15DEC] Max Flow P && 树上差分
    传送门:P3128[USACO15DEC]MaxFlowP首先要学会差分qwq题目意思:给定一个节点数为\(n\)的树,有\(m\)次操作。每次操作给你两个数\(s\)和\(t\),你需要在\(s\)到\(t\)的路径所经过点的运输压力\(+1\)。求最后运输压力最大的点的压力。思路:发现\(s\)到\(t\)的路......