题解
感觉是一道树型 ( ext{dp}) 好题,反正不看题解不会做,我真屑。
题意很简单,给你一张有向树型图,问你拓扑序数量。
因为我们发现如果一棵子树的内部的拓扑序已经确定了,影响这个子树与外面的相对关系的只有根节点,所以我们定义 (f_{i,j}) 为 (i) 在以 (i) 为根的子树中拓扑序位置为 (j) 的方案数。
然后有了这个东西之后我们发现转移就很简单了。
若 (u<v) ,则:
[(new)f_{u,k}=inom{k-1}{i-1}inom{size_u+size_v-k}{size_u-i}cdot f_{u,i}sum_{j=k-i+1}^{size_v}f_{v,j}
]
若 (u>v) ,则:
[(new)f_{u,k}=inom{k-1}{i-1}inom{size_u+size_v-k}{size_u-i}cdot f_{u,i}sum_{j=1}^{k-i}f_{v,j}
]
好像做完了。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e3+5;
const int MOD=1e9+7;
int n,siz[N];
int f[N][N],g[N][N],h[N];
int frac[N],ifrac[N];
int ksm(int x,int k){
int res=1;
for(;k;k>>=1,x=x*x%MOD)
if(k&1) res=res*x%MOD;
return res;
}
int cal(int n,int m){
if(n<0||m<0||n<m) return 0;
return frac[n]*ifrac[m]%MOD*ifrac[n-m]%MOD;
}
struct Edge{int nxt,to,flag;}e[N<<1];int fir[N];
void add(int u,int v,int w,int i){e[i]=(Edge){fir[u],v,w},fir[u]=i;}
void dp(int u,int fa){
siz[u]=1,f[u][1]=1;
for(int i=fir[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
dp(v,u),memset(h,0,sizeof(h));
for(int c=1;c<=siz[u];++c){
for(int d=1;d<=siz[u]+siz[v];++d){
if(e[i].flag){
if(d-c+1>siz[v]) continue;
h[d]+=cal(d-1,c-1)*cal(siz[u]+siz[v]-d,siz[u]-c)%MOD*f[u][c]%MOD*(g[v][siz[v]]-g[v][d-c]+MOD)%MOD;
h[d]%=MOD;
}
else{
if(1>d-c) continue;
h[d]+=cal(d-1,c-1)*cal(siz[u]+siz[v]-d,siz[u]-c)%MOD*f[u][c]%MOD*(g[v][d-c]-g[v][0]+MOD)%MOD;
h[d]%=MOD;
}
}
}
siz[u]+=siz[v];
for(int j=1;j<=siz[u];++j) f[u][j]=h[j];
}
// printf("%lld
",u);
// for(int i=1;i<=siz[u];++i) printf("%lld ",f[u][i]);
// printf("
");
for(int i=1;i<=siz[u];++i){
g[u][i]=(g[u][i-1]+f[u][i])%MOD;
}
}
void solve(){
cin>>n;
for(int i=1;i<n;++i){
int u,v;char s[2];
scanf("%lld%s%lld",&u,s,&v),u++,v++;
add(u,v,s[0]=='<',i<<1);
add(v,u,s[0]=='>',i<<1|1);
}
dp(1,0);
int res=0;
for(int i=1;i<=n;++i) res+=f[1][i],res%=MOD;
return printf("%lld
",res),void();
}
void init(){
memset(fir,0,sizeof(fir));
memset(g,0,sizeof(g));
}
signed main(){
frac[0]=1;
for(int i=1;i<N;++i) frac[i]=frac[i-1]*i%MOD;
ifrac[N-1]=ksm(frac[N-1],MOD-2);
for(int i=N-1;i>=1;--i) ifrac[i-1]=ifrac[i]*i%MOD;
int T;cin>>T;
while(T--) init(),solve();
}