zoukankan      html  css  js  c++  java
  • 树上独立集数量 树型DP

    题目描述:

    对于一棵树,独立集是指两两互不相邻的节点构成的集合。例如,图1有5个不同的独立集(1个双点集合、3个单点集合、1个空集),图2有14个不同的独立集,图3有5536个不同的独立集。 
    这里写图片描述这里写图片描述这里写图片描述

    输入:

    第一行一个正整数n,表示点的数量。n最大为100000。 
    接下来n-1行,有两个整数a、b,表示编号为a、b的两个点之间有一条边,其中a、b大于等于1,小于等于n。 
    17 
    1 2 
    1 3 
    2 4 
    2 5 
    3 6 
    3 7 
    5 8 
    5 9 
    7 10 
    7 11 
    8 12 
    8 13 
    10 14 
    10 15 
    12 16 
    15 17

    输出:

    输出一行,包含一个整数,表示独立集的数量。由于这个数很大,你只需要输出这个数除以10081的余数。

    分析:

    这是一道树形DP。设f[i][0]表示在选i个节点的独集数,f[i][1]表示不选第i个节点的独集数。 
    很明显,每一个节点的f都是有它的子节点得到的。 
    如果选了第i个节点,那么它的子节点全部不选。所以,f[i][0]就等于它的子节点f[j][1]的乘积。 
    反之,不选第i个节点,那么它的子节点可以选也可以不选,f[i][1]等于它的子节点(f[j][0] +f[j][1])的乘积。 
    边就用奇怪的方法维护就行了(不要告诉我你不会前向新或边集数组)。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int mo=10081;
    int n,a[300001][2],g[300001],f[300001][2];
    bool bz[300001];
    void qsort1(int l, int r)  
    {  
        int i=l;  
        int j=r;  
        int x;
        int t;
        x=a[(l+r)/2][0];
        while (i<=j)  
        {  
            while(a[i][0]<x) i++;  
    
            while(a[j][0]>x) j--;  
            if(i<=j)
            {   
                t=a[j][0];
                a[j][0]=a[i][0];  
                a[i][0]=t;
                t=a[j][1];
                a[j][1]=a[i][1];  
                a[i][1]=t;
                j--;
                i++;
            }  
        }    
        if (l<j) qsort1(l,j);  
        if (r>i) qsort1(i,r);  
    }
    void dfs(int x)
    {
        int z1,z2,z=g[x],l=0;
        while (a[z][0]==x)
        {
            if (bz[a[z][1]]==false)
            {
                l=1;
                bz[a[z][1]]=true;
                dfs(a[z][1]);
                f[x][0]=(f[x][0]*f[a[z][1]][1])%mo;
                if (z==g[x]) 
                {
                    z1=f[a[z][1]][0];
                    z2=f[a[z][1]][1];
                }
                else
                {
                    z1=(z1*f[a[z][1]][0]+z1*f[a[z][1]][1])%mo;
                    z2=(z2*f[a[z][1]][0]+z2*f[a[z][1]][1])%mo;
                }
            }
            z++;
        }
        if (l==1) 
        {
            f[x][1]=(z1+z2)%mo;
        }
    }
    int main()
    {
        int i,j,k;
        scanf("%d",&n);
        int zl=0;
        for (i=1;i<=n-1;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            zl++;
            a[zl][0]=x;
            a[zl][1]=y;
            zl++;
            a[zl][0]=y;
            a[zl][1]=x;
        }
        for (i=1;i<=n;i++)
        {
            f[i][1]=1;
            f[i][0]=1;
        }
        qsort1(1,zl);
        int z=1;
        for (i=1;i<=zl;i++)
        {
            if (a[z][0]!=a[i][0])
            {
                g[a[z][0]]=z;
                z=i;
            }
        }
        g[a[z][0]]=z;
        bz[1]=true;
        dfs(1);
        printf("%d",(f[1][0]+f[1][1])%mo);
    }
  • 相关阅读:
    什么是HTTP
    通过递归法解决阶梯问题(n个台阶,上楼可以一步上1阶,也可以一步上2阶,一共有多少种上楼的方法)
    在Intelli Idea中使用plantuml(plantuml时序图的使用)
    Java中if(boolean)与if(boolean=true)的区别
    实现一个Servlet程序
    退出mysql的编辑模式
    mysql数据库基本操作命令行
    通过mysql命令查看mysql服务实例支持的搜索引擎
    Mac环境下使用终端启动Mysql,并进行mysql数据库的连接
    路飞学城Python-Day4
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7554644.html
Copyright © 2011-2022 走看看