• Codeforces 765E. Tree Folding [dfs][树形dp]


    题解:
    先从节点1开始dfs。
    对于每一个节点,用一个set记录:以该点为根的子树的深度。

    a) 如果此节点的某个子节点打出了GG,则此节点直接打出GG。

    b) 若set的元素个数<=1,那么,以该点为根的子树,显然是可以
    缩成一条链滴!且该点为链的端点。
    c) 若set元素个数=2,以该点为根的子树,也可以收缩成一条链,
    且该点不是链的端点。此时,我们继续分类讨论。
      i) 该点没有父亲。我们成功找到了一条链~岂不美哉。
      ii) 该点有父亲,那么在链上会长出一根奇怪的东西。那我们赶紧报警,把该点赋给root,并打出GG
    d)若set中元素个数>2,直接打出GG!

    如果从1开始dfs求索未得,那一定是root的打开方式不对。我萌以root为起点再来一遍dfs。
    如果还不行,那就真.GG。

    #include <iostream>
    #include <vector>
    #include <set>
    #include <cstdio>
    using namespace std;
    const int NICO = 200000 + 10;
    vector<int> vec[NICO];
    int n, u, v, root;
    int dfs(int x, int par)
    {
        set<int> st;
        for(int i=0;i<vec[x].size();i++)
        {
            int cur = vec[x][i];
            if(cur == par) continue;
            int t=dfs(cur, x);
            if(t == -1) return -1;// 子节点都已经报警了,就不要再dfs啦!
            st.insert(t+1);
        }
        if(st.size() == 0) return 0;
        if(st.size() == 1) return *st.begin();
        if(st.size() == 2 && par == 0) return *st.rbegin() + *st.begin();
        root = x;                 // 风起于青萍之末~ 此刻,报警吧!
        return -1;
    }
    int main()
    {
        cin >> n;
        for(int i=1;i<n;i++)
        {
            cin >> u >> v;
            vec[u].push_back(v);
            vec[v].push_back(u);
        }
        int ans = dfs(1, 0);
        if(ans == -1 && root) ans = dfs(root, 0);
        while(ans%2==0)
        {
            ans /= 2;
        }
        cout << ans << endl;
    }
    

      

  • 相关阅读:
    MDK(keil)4.7中文注释乱码解决
    小型功率放大器的设计与制作
    增强输出的电路
    晶体管电路设计学习笔记(一)
    MOSFET学习
    sysTick系统定时器
    C#面向对象 什么是面向对象
    JS基础 超链接、数列的用法,行内元素和块级元素
    JS基础 常用函数、事件、阻止事件冒泡
    JS基础 定时器【setTimeout、setInterval、clearInterval 】
  • 原文地址:https://www.cnblogs.com/RUSH-D-CAT/p/6404742.html
Copyright © 2020-2023  润新知