zoukankan      html  css  js  c++  java
  • 题解-P3174 [HAOI2009]毛毛虫

    (Large exttt{P3174})

    (large exttt{Read in my Blog})

    做法:树形 (DP)

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

    (Large exttt{Meaning})

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

    (Large exttt{Solution})

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

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

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

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

    (Large exttt{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;
    }
    
  • 相关阅读:
    常见概念
    网站扒取
    图书管理系统易错点整理
    CSIC_716_2020104【Django入门---静态文件、request对象方法、ORM增删改查】
    CSIC_716_2020103【Django入门---HttpResponse、render、redirect】
    CSIC_716_2020102【前端框架Bootstrap】
    CSIC_716_2020101【???】
    CSIC_716_20191231【jQuery基础入门】
    CSIC_716_20191230【前端的BOM与DOM】
    ss
  • 原文地址:https://www.cnblogs.com/RedreamMer/p/13428408.html
Copyright © 2011-2022 走看看