[HAOI2009]毛毛虫

2023-11-05 14:32
文章标签 haoi2009 毛毛虫

本文主要是介绍[HAOI2009]毛毛虫,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目

LuoguP3174 [HAOI2009]毛毛虫

分析

可以想到这是一个树形DP:因为题目要求一条链,并且这条链连同其相邻节点所组成的新树最长,所以这就意味着,选择一个节点后,将选择其所有儿子,并且扩展其中一个儿子。
因此可以得到一个暴力做法:枚举每个点,树形DP,设f[i]表示以i为根节点的最长链长度。
转移方程: f[i]=max{f[v]+son[i]1|vi} f [ i ] = m a x { f [ v ] + s o n [ i ] − 1 | v → i } (要减去被选中的点,因为每个点应初始化为1,否则单点情况无法处理,这样就导致被选中的儿子在son[i]中算了一次,在f[v]中又算了一次,也就是被多算了一次)
复杂度取决于儿子大小,即使是一棵二叉树,也有 O(2log2nn)=O(n2) O ( 2 log 2 ⁡ n ∗ n ) = O ( n 2 ) ,显然过不了。
观察树的性质,可以发现:钦定任意一节点为根,那么答案树就是:此节点、其最长链上满足条件的点、次长链上满足条件的点。这一点很难想,不过学会这种思维之后,其他的题目就说不定能想到了。
优化做法:钦定一个节点为根进行dfs,每个节点保存一个次大答案s,最大答案l:

f[u]=max{f[v]+son[i]1|vi},ans=max{l[u]+s[u]+son[u]1}; f [ u ] = m a x { f [ v ] + s o n [ i ] − 1 | v → i } , a n s = m a x { l [ u ] + s [ u ] + s o n [ u ] − 1 } ;

注意更新时要判断f[u]与l、s的大小,逐个更新。

代码

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=300002;
struct Edge{int to,next;
}e[maxn*2];
int head[maxn],f[maxn],son[maxn];
bool vis[maxn];
int n,m,cnt,ans;void add(int u,int v)
{e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;son[u]++;
}void dfs(int u,int fa)
{int s=0,l=0;for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(v==fa)   continue;dfs(v,u);if(f[v]>s){if(f[v]>l)  s=l,l=f[v];else        s=f[v];f[u]=max(f[u],f[v]+son[u]-1);}}ans=max(ans,s+l+son[u]-1);
}int main()
{scanf("%d%d",&n,&m);for(int i=1,x,y;i<=m;i++){scanf("%d%d",&x,&y);add(x,y),add(y,x);}for(int i=1;i<=n;i++)   f[i]=1;dfs(1,0);printf("%d",ans);return 0;
}

这篇关于[HAOI2009]毛毛虫的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/350491

相关文章

IOS控件系列--Swift 滑动标签栏(支持底部下划线毛毛虫滑动效果Object-c实现)

这一编是之前OC版的翻译版本,不过做做了一些新功能的扩展,新功能如下: 1.标签支持自适应文本宽度 2.点击标签文本时,标签文本的滚动列表会跟着一起滑动 3.底部指示线宽度自适应上面标签文本宽度 4.将可滑动的标题栏与不可滑动的标题栏结合到一个接口中   设计思路与前一个版本一致,各位道友请移步查看详细的思路,   IOS 高仿boss直聘---优雅使用UIButton与UIScr

#(树形动规)洛谷P3174 [HAOI2009]毛毛虫(省选/NOi-)

题目描述 对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大。例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 )。 输入格式 在文本文件 worm.in 中第一行两个整数 N , M ,分别表示树中结点个数和树的边数。 接下来 M 行,每行两个整数 a, b 表示点 a 和点 b 有边连接( a, b ≤ N )。