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毛毛虫的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P3174 [HAOI2009]毛毛虫

P3174 [HAOI2009]毛毛虫

P3174 [HAOI2009]毛毛虫

luogu P3174 [HAOI2009] 毛毛虫 树dp

[HAOI2009]毛毛虫

[HAOI2009]毛毛虫(树形dp)