CodeForces - 1252B Cleaning Robots

题意:

给你一棵用 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\n",ans);
72     return 0;
73 }
View Code
posted @ 2020-10-22 14:11  Hzoi_joker  阅读(212)  评论(0编辑  收藏  举报