独立集

来源:互联网 发布:富士康跳樓事件知乎 编辑:程序博客网 时间:2024/04/30 19:50

题目描述:

对于一棵树,独立集是指两两互不相邻的节点构成的集合。例如,图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的余数。
5536


分析:

这是一道树形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])的乘积。
边就用奇怪的方法维护就行了(不要告诉我你不会前向新或边集数组)。


CODE:

#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);}
1 0