NC20008. [HEOI2013]SAO
描述
Welcome to SAO ( Strange and Abnormal Online)。这是一个 VR MMORPG, 含有 n 个关卡。但是,挑战不同关卡的顺序是一个很大的问题。
有 n – 1 个对于挑战关卡的限制,诸如第 i 个关卡必须在第 j 个关卡前挑战, 或者完成了第 k 个关卡才能挑战第 l 个关卡。并且,如果不考虑限制的方向性, 那么在这 n – 1 个限制的情况下,任何两个关卡都存在某种程度的关联性。即, 我们不能把所有关卡分成两个非空且不相交的子集,使得这两个子集之间没有任 何限制。
输入描述
第一行,一个整数T,表示数据组数。
对于每组数据,第一行一个整数n,表示关卡数。
接下来n–1行,每行为“i sign j”,其中0 ≤ i,j ≤ n–1且i≠j,sign为“ < ”或者“ > ”,表示第i个关卡必须在第j个关卡前/后完成
T ≤ 5,1 ≤ n ≤ 1000
输出描述
对于每个数据,输出一行一个整数,为攻克关卡的顺序方案个数,mod1,000,000,007输出。
示例1
输入:
2 5 0 < 2 1 < 2 2 < 3 2 < 4 4 0 < 1 0 < 2 0 < 3
输出:
4 6
C++(clang++ 11.0.1) 解法, 执行用时: 86ms, 内存消耗: 16308K, 提交时间: 2022-09-30 15:58:53
#include<bits/stdc++.h> using namespace std ; #define ll long long const int mod = 1e9 + 7 , N = 2005 ; int jc[N],inv[N] ; int qsm(int a,int b) { int ans=1 ; while(b) { if(b&1) ans=(ll)ans*a%mod ; a=(ll)a*a%mod ; b>>=1 ; } return ans ; } void init(int n=N-1) { jc[0]=1 ; for(int i=1;i<=n;++i) jc[i]=(ll)jc[i-1]*i%mod ; inv[n]=qsm(jc[n],mod-2) ; for(int i=n;i>=1;--i) inv[i-1]=(ll)inv[i]*i%mod ; } int C(int n,int m) { return (ll)jc[n]*inv[m]%mod*inv[n-m]%mod ; } int calc(int x,int y) { return (ll)jc[x+y]*inv[x]%mod*inv[y]%mod ; } int n ; vector<pair<int,int>> g[N] ; int f[N][N],h[N],siz[N] ; int sum(int x,int l,int r) { return (f[x][r]-f[x][l-1]+mod)%mod ; } void dfs(int x,int fa) { siz[x]=1 ; f[x][1]=1 ; for(auto &y:g[x]) { int z=y.first ; if(z==fa) continue ; dfs(z,x) ; memcpy(h,f[x],sizeof(h)) ; memset(f[x],0,sizeof f[x]) ; if(y.second==1) { for(int i=1;i<=siz[x];++i) for(int j=i;j<siz[z]+i;j++) (f[x][j]+=(ll)C(j-1,i-1)*C(siz[x]+siz[z]-j,siz[x]-i)%mod*h[i]%mod*sum(z,j-i+1,siz[z])%mod)%=mod ; } else { for(int i=1;i<=siz[x];++i) for(int j=i+1;j<=siz[z]+i;j++) (f[x][j]+=(ll)C(j-1,i-1)*C(siz[x]+siz[z]-j,siz[x]-i)%mod*h[i]%mod*sum(z,1,j-i)%mod)%=mod ; } siz[x]+=siz[z] ; } for(int i=2;i<=siz[x];++i) (f[x][i]+=f[x][i-1])%=mod ; } void solve() { scanf("%d",&n) ; char ch ; for(int i=1;i<=n;++i) g[i].clear() ; memset(f,0,sizeof(f)) ; memset(siz,0,sizeof(siz)) ; for(int i=1,x,y;i<n;++i) { scanf("%d %c %d",&x,&ch,&y) ; x++ ; y++ ; g[x].push_back({y,ch=='<'}) ; g[y].push_back({x,ch=='>'}) ; } dfs(1,0) ; printf("%d\n",f[1][n]) ; } int main() { init() ; int T ; scanf("%d",&T) ; while(T--) solve() ; return 0 ; }