zoukankan      html  css  js  c++  java
  • [HAOI2009]毛毛虫(树形dp)

    [HAOI2009]毛毛虫

    题目描述

    对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大。例如下图左边的树(图 1 )抽出一部分就变成了右边的一个毛毛虫了(图 2 )。

    输入输出格式

    输入格式:

    在文本文件 worm.in 中第一行两个整数 N , M ,分别表示树中结点个数和树的边数。

    接下来 M 行,每行两个整数 a, b 表示点 a 和点 b 有边连接( a, b ≤ N )。你可以假定没有一对相同的 (a, b) 会出现一次以上。

    输出格式:

    在文本文件 worm.out 中写入一个整数 , 表示最大的毛毛虫的大小。

    输入输出样例

    输入样例#1: 复制

    13 12
    1 2
    1 5
    1 6
    3 2
    4 2
    5 7
    5 8
    7 9
    7 10
    7 11
    8 12
    8 13

    输出样例#1: 复制

    11

    说明

    40% 的数据, N ≤ 50000

    100% 的数据, N ≤ 300000

    题解

    我真傻,真的。
    我一开始以为以1为根节点。
    然后找两条分链加加起来就好了。
    测一下60分,以为是对的。
    于是。。。。6点到10点,没有调出来,生无可恋。

    最后还是看题解了。我真菜

    我怎么就没想到要把每一个点作为一次根呢
    然后因为是相连的点换根。所以子树的变化就是原根少一个点的子树,那个点的子树加上原根。
    dp判断一下当前f[i]表示以i为根的最大长度。
    然后毛毛虫可以是拼起来的。也就是说要记录最长和次长链。
    end.

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int N=300005;
    struct node{
        int nex,to;
    }e[N<<1];
    int size[N],n,m,num,head[N];
    int f[N],ans,pre[N];
    void add(int from,int to){
        num++;
        e[num].to=to;
        e[num].nex=head[from];
        head[from]=num;
    }
    
    int read(){
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    
    void dfs(int x,int fa){
        size[x]=1;//int sum=0;
        for(int i=head[x];i;i=e[i].nex){
            int v=e[i].to;
            if(v==fa)continue;
            size[x]++;dfs(v,x);
        }
    }
    
    void dfs2(int x,int fa){
        int max1=0,max2=0;
        for(int i=head[x];i;i=e[i].nex){
            int v=e[i].to;
            if(v==fa)continue;
            dfs2(v,x);
            if(f[v]>max1){
                max2=max1;max1=f[v];
            }
            else if(f[v]>max2)max2=f[v];
            f[x]=max(f[x],f[v]+size[x]-1);
        }
        ans=max(ans,max1+max2-1+size[x]);
    }
    
    int main(){
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            add(x,y);add(y,x);
            size[x]++;size[y]++;
        }
        for(int i=1;i<=n;i++)f[i]=1;
        dfs2(1,0);
        printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    jQuery Colorpicker Spectrum api 中文 文档 属性 事件 方法
    java使用dbutils工具类实现小程序 管家婆记账软件
    java实现服务端开启多线程处理客户端的上传图片请求
    java 基于tcp客户端服务端发送接收数据
    java基于udp实现键盘录入聊天
    java实现udp发送端和接收端
    java通过读取本地文件获取反射方法参数,执行对象方法
    java通过反射获取私有的构造方法,及反射擦除泛型数据类型约束
    Java反射获取类对象的三种方式
    java使用DBCP连接池创建工具类
  • 原文地址:https://www.cnblogs.com/hhh1109/p/9603546.html
Copyright © 2011-2022 走看看