Loading

题解 【P3174 [HAOI2009]毛毛虫】

\(\Large\texttt{P3174}\)

\(\large\texttt{Read in my Blog}\)

做法:树形 \(DP\)

题目中的 \(M\) 到底有什么用啊QwQ

\(\Large\texttt{Meaning}\)

题目“抽”字我一开始看还是有点迷惑的,其实实意就是在一棵树中取一条链,求链上的点和与它们相邻的点的个数最大。

\(\Large\texttt{Solution}\)

考虑每一个点 \(n\)这条链经过点 \(n\) ,那么一定是从 \(n\) 的一棵子树的叶子开始,到另一棵子树的叶子,显然这肯定是最大的。

这样,我们就要记录每个点两个值:与它相邻的节点个数(包括它,不包括父节点);从这个节点到它子树的某个叶子节点,这条链上有贡献的节点个数(不包括父节点),令第一个记录值为数组 \(s\) ,第二个记录值数组 \(h\)

\(s[n]\) 很好求, \(h[n]\) 即为 \(s[n]-1+\max_{v\in n} h[v]\)(因为 \(s[n]\)\(h[v]\) 都包括了 \(v\) 这个节点),但是注意若 \(n\) 事叶子节点,不用减一。

然后就可以求我们想要求的链了,记录子节点中最大和次大的的 \(h\) 值, 加上这个节点的相邻节点个数( \(s[n]\) )就好了,但要注意判重,和细节(见代码)。

\(\Large\texttt{Code}\)

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <map>
#include <iostream>
#include <iterator>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
// #include <bits/stdc++.h>
using namespace std;

// #define ls now << 1
// #define rs now << 1 | 1
#define PB push_back
// #define MP make_pair
// #define int long long
// #define us unsigned
// #define LL long long
const int N = 300000;
// const int M = 1e3;
// #define re register
// const int mod = 1e;
// const int inf = 0x7fffffff;
// const double inf_double = 1e4;
// const double eps = 1e-4;

int a, siz[N + 10], ans, dp[N + 10], s[N + 10], h[N + 10];
vector<int> st[N + 10];

inline void dfs(int n, int fa)
{
    s[n] = 1;
    h[n] = 1;
    int mx1 = 0, mx2 = 0;
    for (int i = 0; i < st[n].size(); i++)
    {
        int v = st[n][i];
        if (v == fa)
            continue;
        dfs(v, n);
        s[n]++;
        h[n] = max(h[n], h[v]);
        if (h[v] >= mx1)
        {
            mx2 = mx1;//顺序不要错
            mx1 = h[v];
        }
        else if (h[v] > mx2)
            mx2 = h[v];
    }
    h[n] += s[n];
    if (st[n].size())//不是叶子节点的时候
        h[n]--;
    int tmp = mx1 + mx2 + s[n] - (mx1 != 0) - (mx2 != 0) + (fa != 0);//注意孩子节点的个数少于2的时候,和没有父节点的时候。
    ans = max(ans, tmp);//记录当前最大值
}

signed main()
{
    scanf("%d%*d", &a);
    int x, y;
    for (int i = 1; i < a; i++)
    {
        scanf("%d%d", &x, &y);
        st[x].PB(y);
        st[y].PB(x);
    }
    dfs(1, 0);
    printf("%d", ans);
    return 0;
}
posted @ 2020-08-03 20:17  RedreamMer  阅读(142)  评论(0编辑  收藏  举报