【Luogu】P3174毛毛虫(树形DP)

  题目链接

  树形DP水题,设f[x][0]是以x为根的子树,内部只有半条链(就是链的两个端点一个在子树里,一个不在子树里)的最大值,f[x][1]是以x为根的子树,内部有一条完整的链(选两个内部的子树作为链的左端点和右端点)的最大值。

  于是可以很轻松的得出DP方程:

  一开始f[x][0]=f[x][1]=1

  然后dfs,深搜x的子树,记录一下x有多少子节点的同时记录子树的最大半链和次大半链(用来在转移的时候凑成x子树内的整个链)。最后注意细节乱搞搞就行了。

  本题不考思维但是比较考验考虑细节的能力。

  (具体有哪些坑点不知道,因为是1A)

  

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define maxn 300010
using namespace std;
inline long long read(){
    long long num=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')    f=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        num=num*10+ch-'0';
        ch=getchar();
    }
    return num*f;
}

int f[maxn][2];

struct Edge{
    int next,to;
}edge[maxn*3];
int head[maxn],num;
inline void add(int from,int to){
    edge[++num]=(Edge){head[from],to};
    head[from]=num;
}

void dfs(int x,int fa){
    int fir=0,sec=0,son=0;
    f[x][1]=f[x][0]=1;
    for(int i=head[x];i;i=edge[i].next){
        int to=edge[i].to;
        if(to==fa)    continue;
        son++;
        dfs(to,x);
        if(fir<f[to][0]){
            sec=fir;fir=f[to][0];
        }
        else if(sec<f[to][0])    sec=f[to][0];
    }
    if(son>1)    f[x][1]=max(f[x][1],fir+sec+son-1);
    else         f[x][1]=max(f[x][1],fir+1);
    f[x][0]=max(f[x][0],fir+son);
}

int main(){
    int n=read(),m=read();
    for(int i=1;i<=m;++i){
        int x=read(),y=read();
        add(x,y);
        add(y,x);
    }
    dfs(1,1);
    int ans=f[1][1];
    for(int i=2;i<=n;++i)    ans=max(ans,f[i][1]+1);
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-01-26 16:40  Konoset  阅读(230)  评论(0编辑  收藏  举报