• [HAOI2009]毛毛虫


    题目描述

    对于一棵树,我们可以将某条链和与该链相连的边抽出来,看上去就象成一个毛毛虫,点数越多,毛毛虫就越大。

    输入输出格式

    输入格式:
    在文本文件 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

    又是一道省选题。。。


    题解

    题目要我们找一条链,使链上的点数和与它相连的边数最大神TM毛毛虫
    显然是一道树形DP题。先用一个数组t表示每个点所连的边数,f[i]表示从i的子树中一点到i的毛毛虫大小,为了方便,我把i当成,设v为它儿子,则f[i]=max{f[v]+t[u]-1},你可能会想,怎么统计答案?
    我们设ma1为u所有儿子vk中最大的f[vk],ma2为次大的f[vk],ans=max{ma1+ma2+t[u]-1};


    常数巨大的丑陋代码

    # include <stdio.h>
    # include <stdlib.h>
    # include <iostream>
    # include <string.h>
    # include <math.h>
    using namespace std;
    
    # define IL inline
    # define RG register
    # define UN unsigned
    # define ll long long
    # define rep(i, a, b) for(RG int i = a; i <= b; i++)
    # define per(i, a, b) for(RG int i = b; i >= a; i--)
    # define uev(e, u) for(RG int e = ft[u]; e != -1; e = edge[e].nt)
    # define mem(a, b) memset(a, b, sizeof(a))
    # define max(a, b) ((a) > (b)) ? (a) : (b)
    # define min(a, b) ((a) < (b)) ? (a) : (b)
    
    IL int Get(){
        RG char c = '!'; RG int num = 0, z = 1;
        while(c != '-' && (c > '9' || c < '0')) c = getchar();
        if(c == '-') z = -1, c = getchar();
        while(c >= '0' && c <= '9') num = num * 10 + c - '0', c = getchar();
        return num * z;
    }
    
    const int MAXN = 300001, INF = 2147483647;
    struct Edge{
        int to, nt;
    } edge[MAXN << 1];
    int n, cnt, ft[MAXN], m, ans, t[MAXN], f[MAXN];
    
    IL void Add(RG int u, RG int v){
        edge[cnt] = (Edge){v, ft[u]}; ft[u] = cnt++; t[u]++;
    }
    
    IL void Dfs(RG int u, RG int fa){
        RG int ma1 = 0, ma2 = 0;
        uev(e, u){
            RG int v = edge[e].to;
            if(v == fa) continue;
            Dfs(v, u);
            if(f[v] > ma1) ma2 = ma1, ma1 = f[v];
            else if(f[v] > ma2) ma2 = f[v];
            f[u] = max(f[u], f[v] + t[u] - 1);
        }
        ans = max(ans, ma1 + t[u] - 1 + ma2);
    }
    
    int main(){
        mem(ft, -1);
        n = Get(); m = Get();
        rep(i, 1, n) f[i] = 1;
        rep(i, 1, m){
            RG int u = Get(), v = Get();
            Add(u, v); Add(v, u);
        }
        Dfs(1, 0);
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    codeforces431C
    codeforces158C
    codeforces570C
    codeforces472C
    codeforces401C
    codeforces630C
    codeforces581C
    校内题目腐草为萤
    校内题目大美江湖
    洛谷P3370 && 字符串哈希讲解
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8206417.html
Copyright © 2020-2023  润新知