zoukankan      html  css  js  c++  java
  • CodeForces

    题意:

    给你一棵用 N 个点构成的树,问这 n 个点有多少种划分方案。一种划分方案合法当且仅当这种划分方案将所有点分成若干集合,每一个集合中的点正好可以构成一条链,没有两个集合所形成的链可以首尾相接,一个点也算链。

    题解:

    这道题还是比较显然的树上DP,一开始想的是设f[x][0/1/2],0 表示 x 这个点不可能向上连边,1 表示 x 这个点可以向上连边也可以不连边, 2 表示这个点一定向上连边。这么设状态向上很好转移,但是平级就很难,所以我设f[x][0/1/2/3/4]。

    0表示x这个点没有儿子有向他连边的可能

    1表示这个点有一个或以上的儿子有向他连边的可能

    2表示这个点已经和一个儿子连边,且没有其他儿子有向他连边的可能

    3表示这个点已经和一个儿子连边,且有其他儿子有向他连边的可能

    4表示这个点已经和两个儿子连边

    这样,虽然状态数变多了,但是儿子与儿子之间,儿子与父亲之间的转移变得更加清晰。

     1 #include<cstdlib>
     2 #include<cstdio>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<cmath>
     7 #define N 100005
     8 using namespace std;
     9 int n;
    10 int zz,a[N];
    11 const int p=1e9+7;
    12 struct ro{
    13     int to,next;
    14 }road[N*2];
    15 void build(int x,int y)
    16 {
    17     zz++;
    18     road[zz].to=y;
    19     road[zz].next=a[x];
    20     a[x]=zz;
    21 }
    22 int fa[N];
    23 long long F[N][10];
    24 void dfs(int x)
    25 {
    26     long long f[2][10];
    27     memset(f,0,sizeof(f));
    28     int nw=1,la=0;
    29     f[nw][0]=1;
    30     for(int i=a[x];i;i=road[i].next)
    31     {
    32         int y=road[i].to;
    33         if(y==fa[x])continue;
    34         fa[y]=x;
    35         dfs(y);
    36         nw^=1,la^=1;
    37         memset(f[nw],0,sizeof(f[nw]));
    38         f[nw][0]=f[la][0]*F[y][4]%p;
    39         f[nw][1]=(f[la][0]*((F[y][0]+F[y][2])%p))%p+(f[la][1]*((F[y][0]+F[y][2]+F[y][4])%p))%p;
    40         f[nw][1]%=p;
    41         f[nw][2]=(f[la][0]*((F[y][0]+F[y][2]+F[y][3])%p))%p+f[la][2]*F[y][4]%p;
    42         f[nw][2]%=p;
    43         f[nw][3]=(f[la][1]*((F[y][0]+F[y][2]+F[y][3])%p))%p+(f[la][2]*((F[y][0]+F[y][2])%p))%p+(f[la][3]*((F[y][0]+F[y][2]+F[y][4])%p))%p;
    44         f[nw][3]%=p;
    45         f[nw][4]=((f[la][2]+f[la][3])%p*((F[y][0]+F[y][2]+F[y][3])%p))%p+(f[la][4]*((F[y][0]+F[y][2]+F[y][4])%p))%p;
    46         f[nw][4]%=p;        
    47     }
    48     for(int i=0;i<=4;i++) F[x][i]=f[nw][i];
    49 }
    50 
    51 int main()
    52 {
    53     scanf("%d",&n);
    54     for(int i=1;i<n;i++)
    55     {
    56         int x,y;
    57         scanf("%d%d",&x,&y);
    58         build(x,y);
    59         build(y,x);
    60     }
    61     dfs(1);
    62 /*    for(int i=1;i<=n;i++)
    63     {
    64         for(int j=0;j<=4;j++)
    65         {
    66             cout<<F[i][j]<<' ';
    67         }
    68         cout<<endl;
    69     }*/
    70     long long ans=(F[1][0]+F[1][2]+F[1][4])%p;
    71     printf("%lld
    ",ans);
    72     return 0;
    73 }
    View Code
  • 相关阅读:
    element表格添加序号
    ZOJ 3822 Domination(概率dp)
    HDU 3037(Lucas定理)
    HDU 5033 Building(单调栈维护凸包)
    HDU 5037 Frog(贪心)
    HDU 5040 Instrusive(BFS+优先队列)
    HDU 5120 Intersection(几何模板题)
    HDU 5115 Dire Wolf(区间dp)
    HDU 5119 Happy Matt Friends(dp+位运算)
    C++ string详解
  • 原文地址:https://www.cnblogs.com/liutianrui/p/13857949.html
Copyright © 2011-2022 走看看