hdu6820 Tree 2020杭电hdu多校第5场1007

http://acm.hdu.edu.cn/showproblem.php?pid=6820

树形DP裸题,不知道为啥过得不是很多,可能都被前期题卡住了没看这题

sumkj1[v]表示以v为根节点选k-1个子节点并且全部满足度数不超过k的最大连通块的边权和

sum[v]=sumkj1[v]+e[u][v].l,也就是包含一条连向父亲的节点

这个用一遍dfs就能处理出来,每次排个序取最大的k-1个子节点

第二遍dfs求把父节点fa当做子树到u的满足条件的最大连通块的边权和存到u所连向的点的g[v,l]中,其中 l 表示v子树的最大值

然后我们假设把u当那个超过k的,也就是把g[u]中所有的子节点的l加起来,更新一下最大值

最后枚举u的每个子节点v,算出对应的nfmx,也就是v把u当子节点的满足条件的最大边权和,传递给v

 

#include
using namespace std;
typedef long long ll;

const int maxl=2e5+10;

int n,k;
ll ans;
struct ed
{
	int to;ll l;
	bool operator < (const ed &b)const
	{
		return l>b.l;
	}
};
vector e[maxl],g[maxl];
ll sumkj1[maxl],sum[maxl];

inline void prework()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
		e[i].clear(),g[i].clear();
	int u,v,l;
	for(int i=1;i<=n-1;i++)
	{
		scanf("%d%d%d",&u,&v,&l);
		e[u].push_back(ed{v,l});
		e[v].push_back(ed{u,l});
	}
	
}

inline void dfs1(int u,int fa)
{
	int v;
	for(ed ee:e[u])
	{
		v=ee.to;
		if(v==fa) continue;
		dfs1(v,u);
		sum[v]=ee.l+sumkj1[v];
		g[u].push_back(ed{v,sum[v]});
	}
	sort(g[u].begin(),g[u].end());
	int len=g[u].size();len=min(len,k-1);
	sumkj1[u]=0;
	for(int i=0;i

 

你可能感兴趣的:(树形DP)