Luogu4099[HEOI2013]SAO

Luogu4099[HEOI2013]SAO

题面:洛谷

解析

计算方案个数,考虑动态规划:设\(f(u,j)\)表示在以\(u\)为根的子树中,\(u\)\(j\)个被删除的方案数,考虑转移:

设当前\(u\)的删除序列长\(x\)\(v\)的删除序列长\(y\),枚举子树\(v\)中有\(j\)个数先于\(u\)删除,那么有:

\(case1.u<v\)

\[f(u,i+j)=C(i+j-1,i-1)*C(x+y-i-j,y-j)*f(u,i)*f(v,k)(k>j) \]

\(case2.u>v\)

\[f(u,i+j)=C(i+j-1,i-1)*C(x+y-i-j,y-j)*f(u,i)*f(v,k)(k<=j) \]

\(k\)前缀和优化转移即可。

代码


// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#define N 1005
using namespace std;
const int P=1e9+7;
int n,f[N][N],C[N][N],tmp[N];
#define gc() getchar()
inline int In(){
    char c=gc(); int x=0,ft=1;
    for(;c<'0'||c>'9';c=gc()) if(c=='-') ft=-1;
    for(;c>='0'&&c<='9';c=gc()) x=x*10+c-'0';
    return x*ft;
}
inline void Get_C(){
    for(int i=0;i<=1e3;++i){
        C[i][0]=1;
        for(int j=1;j<=i;++j) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
    }
}
int h[N],sz[N],e_tot=0;
struct E{ int to,nex,op; }e[N<<1];
inline void init(){
    e_tot=0;
    memset(h,0,sizeof(h));
    memset(f,0,sizeof(f));
}
inline void Add(int u,int v,int op){
    e[++e_tot]=(E){v,h[u],op}; h[u]=e_tot;
    e[++e_tot]=(E){u,h[v],!op}; h[v]=e_tot;
}
void dfs(int u,int fa){
    sz[u]=1; f[u][1]=1;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to; if(v==fa) continue; dfs(v,u);
        if(!e[i].op){
            for(int i=1;i<=sz[u];++i) tmp[i]=f[u][i],f[u][i]=0;
            for(int i=1;i<=sz[u];++i)
            for(int j=0;j<=sz[v];++j)
            f[u][i+j]=(f[u][i+j]+1ll*C[i+j-1][i-1]*C[sz[u]+sz[v]-i-j][sz[v]-j]%P*tmp[i]%P*((f[v][sz[v]]-f[v][j]+P)%P)%P)%P;
        }//u<v
        else{
            for(int i=1;i<=sz[u];++i) tmp[i]=f[u][i],f[u][i]=0;
            for(int i=1;i<=sz[u];++i)
            for(int j=0;j<=sz[v];++j)
            f[u][i+j]=(f[u][i+j]+1ll*C[i+j-1][i-1]*C[sz[u]+sz[v]-i-j][sz[v]-j]%P*tmp[i]%P*f[v][j]%P)%P;
        }//u>v
        sz[u]+=sz[v];
    }
    for(int i=1;i<=sz[u];++i) f[u][i]=(f[u][i]+f[u][i-1])%P;
}
int main(){
    int T=In(); Get_C(); char str[5];
    while(T--){
        n=In(); init();
        for(int i=1,u,v;i<n;++i){
            u=In(); scanf("%s",str); v=In();
            ++u; ++v; Add(u,v,(str[0]=='>'));
        }
        dfs(1,-1); printf("%d\n",f[1][n]);
    }
    return 0;
}


posted @ 2019-03-14 21:41  pkh68  阅读(143)  评论(0编辑  收藏  举报