P3174-HAOI2009毛毛虫
Posted 14long
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3174-HAOI2009毛毛虫相关的知识,希望对你有一定的参考价值。
3174-HAOI2009毛毛虫
题意:给定一棵树,在树上找出一条链,使得这条链和连接的所有边上的所有点的个数最大(也就是题目中的毛毛虫)。
题解:直接用dp[now][0/1]表示当前节点的子树上的最大毛毛虫,[0/1]表示是否经过根节点似乎是很难做出转移方程的,,因为可以把两条链和起来形成一个毛毛虫,所以考虑dp[i][0/1]表示当前节点的子树上最大的两条分毛毛虫,且这两条毛毛虫在i点处相交。于是有:
\\[dp[now]=max(dp[son]+edge[now]-1)
\\]
- 减1是因为dp[son]已经算上了now节点和son节点,需要减去一个son节点而且不用重复计算now节点。
- 转移的时候同时维护最大值和次大值即可。
#include <bits/stdc++.h>
using namespace std;
#define endl \'\\n\'
const int maxn=3e5+10;
const ll inf=1e16;
int n,m;
vector<int> yuan[maxn];
int dp[maxn][2];
void dfs(int now,int fa){
if(yuan[now].size()==1&&yuan[now][0]==fa){
dp[now][0]=2;return;
}
for(int i=0;i<yuan[now].size();i++){
int v=yuan[now][i];
if(v==fa) continue;
dfs(v,now);
ll ne=dp[v][0]+(int)yuan[now].size()-1;
if(ne>=dp[now][0]){
dp[now][1]=dp[now][0];
dp[now][0]=ne;
continue;
}
else if(ne<dp[now][0]&&ne>=dp[now][1]){
dp[now][1]=ne;
continue;
}
else continue;
}
}
signed main(){
cin>>n>>m;
if(n==1){
cout<<1<<endl;
return 0;
}
for(int i=1;i<=m;i++){
int a1,a2;cin>>a1>>a2;
yuan[a1].push_back(a2);yuan[a2].push_back(a1);
}
dfs(1,0);
ll ans=0;
for(int i=1;i<=n;i++){
if(dp[i][1]!=0) ans=max(ans,dp[i][0]+dp[i][1]-((int)yuan[i].size()+1));
else ans=max(ans,dp[i][0]);
}
cout<<ans<<endl;
return 0;
}
以上是关于P3174-HAOI2009毛毛虫的主要内容,如果未能解决你的问题,请参考以下文章