题目描述
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 个关卡前或后完成。
输出格式
对于每个数据,输出一行一个整数,为攻克关卡的顺序方案个数,mod(109+7) 输出。
输入输出样例
输入 #1复制
2
5
0 < 2
1 < 2
2 < 3
2 < 4
4
0 < 1
0 < 2
0 < 3
输出 #1复制
4
6
说明/提示
对于 20% 的数据有 n≤10。
对于 40% 的数据有 n≤100。
对于另外 20% 的数据有,保证数据中 sign 只会是 <,并且 i<j。
对于 100% 的数据有 T≤5,1≤n≤1000。
代码实现:
cpp
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline ll rd() {
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
ll pow(ll x,ll y,ll p) {
ll ans=1;
for(;y;y>>=1,x=x*x%p)
if(y&1) ans=ans*x%p;
return ans;
}
ll gcd(ll x,ll y) {
if(y==0) return x;
return gcd(y,x%y);
}
ull cnt,MOD,g[1010][1010],T,f[1010][1010],C[2010][2010],e[1010][1010],sz[101000];
ll a[101000],b[101000],c[101000],d[101000],ans,n,i,x,y;
string s;
void add(int x,int y,int z) {
cnt++;a[cnt]=y;b[cnt]=d[x];c[cnt]=z;d[x]=cnt;
}
void dfs(int x,int fa) {
int i,p1,p2,p3;
sz[x]=1;f[x][1]=1;
for(i=d[x];i;i=b[i]) {
if(a[i]==fa) continue;
dfs(a[i],x);
if(c[i]==1) {
for(p1=1;p1<=sz[x]+sz[a[i]];p1++) e[x][p1]=0;
g[a[i]][sz[a[i]]]=f[a[i]][sz[a[i]]];g[a[i]][sz[a[i]]+1]=0;
for(p1=sz[a[i]]-1;p1>=1;p1--) g[a[i]][p1]=(g[a[i]][p1+1]+f[a[i]][p1])%MOD;
for(p1=sz[x];p1>=1;p1--)
for(p3=0;p3<=sz[a[i]]-1;p3++)
e[x][p1+p3]=(e[x][p1+p3]+f[x][p1]*g[a[i]][p3+1]%MOD*C[p1+p3-1][p3]%MOD*C[sz[x]-p1+sz[a[i]]-p3][sz[a[i]]-p3]%MOD)%MOD;
} else {
for(p1=1;p1<=sz[x]+sz[a[i]];p1++) e[x][p1]=0;
for(p1=1;p1<=sz[a[i]];p1++) g[a[i]][p1]=(g[a[i]][p1-1]+f[a[i]][p1])%MOD;
for(p1=sz[x];p1>=1;p1--)
for(p3=1;p3<=sz[a[i]];p3++)
e[x][p1+p3]=(e[x][p1+p3]+f[x][p1]*g[a[i]][p3]%MOD*C[p1+p3-1][p3]%MOD*C[sz[x]-p1+sz[a[i]]-p3][sz[a[i]]-p3]%MOD)%MOD;
}
for(p1=1;p1<=sz[x]+sz[a[i]];p1++) f[x][p1]=e[x][p1];
sz[x]+=sz[a[i]];
}
}
int main() {
ios::sync_with_stdio(0);cin.tie();cout.tie();
cin>>T;MOD=1e9+7;
C[0][0]=1;
for(i=1;i<=2000;i++) {
C[i][0]=1;C[i][i]=1;
for(ull j=1;j<i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
}
for(;T;T--) {
cin>>n;cnt=0;
for(i=1;i<=n;i++) d[i]=0,sz[i]=0;
for(i=1;i<n;i++) {
cin>>x>>s>>y;
x++;y++;
if(s=="<") add(x,y,1),add(y,x,2);
else add(x,y,2),add(y,x,1);
}
for(i=1;i<=n;i++)
for(ull j=1;j<=n;j++)
f[i][j]=0;
dfs(1,0);
ans=0;
for(i=1;i<=n;i++) ans=(ans+f[1][i])%MOD;
printf("%llu\n",ans);
}
return 0;
}