• BZOJ 1149 风铃(树形DP)


    题目描述的实际是一颗二叉树,对于每个结点,要么满叉,要么无叉。

    对于一种无解的简单情况,我们搜一遍树找到最浅的叶子结点1和最深的叶子结点2,如果dep[1]<dep[2]-1,则显然无解。

    所以现在所有的叶子结点的深度要么是dep[1]和dep[2].

    我们可以把所有结点用node[x]标记状态。

    node[x]=0表示x的子树下所有叶子结点深度都是dep[2]。 

    node[x]=1表示x的子树下一部分叶子结点深度是dep[1],一部分是dep[2]。

    node[x]=2表示x的子树下所有叶子结点深度都是dep[1]。

    现在有,假设x的儿子结点的node值都是1,则一定无解。证明是显然的。

    假设x的左儿子结点node值大于右儿子结点的node值,则ans+1,表示需要操作一次。证明也是显然的。

    另外node值可以通过一次树形DP得到,所以总复杂度为O(n).

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi acos(-1.0)
    # define eps 1e-8
    # define MOD 1000000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=100005;
    //Code begin...
    
    int pos, mi=INF, ma=0, node[N*10], dep[N*10], n, ans, son[N][2];
    
    void dfs1(int x)
    {
        if (x>n) mi=min(mi,dep[x]), ma=max(ma,dep[x]);
        else {
            dep[son[x][0]]=dep[son[x][1]]=dep[x]+1;
            dfs1(son[x][0]), dfs1(son[x][1]);
        }
    }
    bool dfs2(int x)
    {
        if (x>n) {
            if (dep[x]<ma) node[x]=2;
            else node[x]=0;
        }
        else {
            if (dfs2(son[x][0])==0 || dfs2(son[x][1])==0) return 0;
            if(node[son[x][0]]==1&&node[son[x][1]]==1) return 0;
            else if (node[son[x][0]]==2&&node[son[x][1]]==2) node[x]=2;
            else if (node[son[x][0]]==0&&node[son[x][1]]==0) node[x]=0;
            else {
                if (node[son[x][0]]>node[son[x][1]]) ++ans;
                node[x]=1;
            }
        }
        return 1;
    }
    int main ()
    {
        int u, v;
        scanf("%d",&n);
        pos=n;
        FOR(i,1,n) {
            scanf("%d%d",&u,&v);
            if (u==-1) u=++pos;
            if (v==-1) v=++pos;
            son[i][0]=u, son[i][1]=v;
        }
        dfs1(1);
        if (mi<ma-1||dfs2(1)==0) puts("-1");
        else printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    【板+背包】多重背包 HDU Coins
    【板+并查集判断连通性】并查集判断连通性
    【Dijstra堆优化】HDU 3986 Harry Potter and the Final Battle
    【区间筛】2017多校训练四 HDU6069 Counting Divisors
    【构造+DFS】2017多校训练三 HDU 6060 RXD and dividing
    【链表】2017多校训练三 HDU 6058 Kanade's sum
    【带权并查集】HDU 3047 Zjnu Stadium
    【优先级队列】 Holedox Eating
    ajax学习笔记3-jQuery实现ajax(大拇指向上)
    ajax学习笔记2-JSON形式返回(大拇指向上)
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6531455.html
Copyright © 2020-2023  润新知