洛谷P4099 [HEOI2013]SAO(树形dp)

传送门

 

HEOI的题好珂怕啊(各种意义上)

然后考虑树形dp,以大于为例

设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小有关,与实际数值无关)

我们考虑如果从当前子树中弄出$k$个节点,其他子树中弄出$j-1$个节点,那么当前节点的大小排名就是$k+j$

然后考虑一下,如果我们不看这个子树,根节点排在第$j$个,方案数是$f[i][j]$,如果只看此子树,此子树的根就是根节点的儿子,它在此子树中的排名可能是$1,2,...k$,那么我们就需要记录一下前缀和

然后考虑合并排列

对于小于根节点的,选出$j-1$个非此子树,对于大于根节点的,选出$sum[x]-1$个非此子树里弄出来的,那么就是一个组合问题了

ps:因为dp的时候会有4个1e9相乘所以要模四次

然后上我这个卡常卡到丧心病狂的代码

 1 // luogu-judger-enable-o2
 2 //minamoto
 3 #include<iostream>
 4 #include<cstdio>
 5 #include<cstring>
 6 #define ll long long
 7 using namespace std;
 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 9 char buf[1<<21],*p1=buf,*p2=buf;
10 inline int read(){
11     #define num ch-'0'
12     char ch;bool flag=0;int res;
13     while(!isdigit(ch=getc()))
14     (ch=='-')&&(flag=true);
15     for(res=num;isdigit(ch=getc());res=res*10+num);
16     (flag)&&(res=-res);
17     #undef num
18     return res;
19 }
20 inline int getop(){
21     char ch;while((ch=getc())!='<'&&ch!='>');return ch=='<'?1:-1;
22 }
23 void print(int x){
24     if(x>=10) print(x / 10);
25     putchar('0'+x%10);
26 }
27 const int N=1005,mod=1e9+7;
28 int n,tot;ll tmp[N];
29 int f[N][N],g[N][N],c[N][N];
30 int head[N],ver[N<<1],Next[N<<1],sum[N],edge[N<<1];
31 inline void init(){
32     c[0][0]=1;
33     for(int i=1;i<=1000;++i){
34         c[i][0]=1;
35         for(int j=1;j<=i;++j)
36         c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
37     }
38 }
39 inline void clear(){
40     memset(head,0,sizeof(head));
41     tot=0;
42 }
43 inline void add(int u,int v,int e){
44     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;
45 }
46 void dfs(int u,int fa){
47     memset(g[u],0,sizeof(g[u])),memset(f[u],0,sizeof(f[u]));
48     g[u][1]=f[u][1]=sum[u]=1;
49     for(int i=head[u];i;i=Next[i]){
50         int v=ver[i],e=edge[i];
51         if(v==fa) continue;
52         dfs(v,u);
53         memset(tmp,0,sizeof(tmp));
54         for(int j=1;j<=sum[u];++j)
55         for(int k=0;k<=sum[v];++k){
56             if(~e)
57             tmp[j+k]+=1ll*f[u][j]*g[v][k]%mod
58             *c[j+k-1][j-1]%mod*c[sum[u]+sum[v]-j-k][sum[u]-j]%mod;
59             else tmp[j+k]+=1ll*f[u][j]*(g[v][sum[v]]-g[v][k]+mod)%mod
60             *c[j+k-1][j-1]%mod*c[sum[u]+sum[v]-j-k][sum[u]-j]%mod;
61         }
62         sum[u]+=sum[v];
63         for(int j=1;j<=sum[u];++j)
64         f[u][j]=tmp[j]%mod,g[u][j]=(g[u][j-1]+f[u][j])%mod;
65     }
66 }
67 int main(){
68 //    freopen("testdata.in","r",stdin);
69     int T=read();init();
70     while(T--){
71         clear();n=read();
72         for(int i=1,u,v,e;i<n;++i){
73             u=read(),e=getop(),v=read();
74             add(u,v,e),add(v,u,-e);
75         }
76         dfs(1,-1);
77         print(g[1][sum[1]]),putchar(10);
78     }
79     return 0;
80 }

 

posted @ 2018-09-14 18:07  bztMinamoto  阅读(239)  评论(0编辑  收藏  举报
Live2D