[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;
}
原文地址:https://www.cnblogs.com/cjoieryl/p/8206417.html