题目描述
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 1,000,000,007 输出。
输入输出样例
输入 #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。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 struct Node 8 { 9 int next,to,w; 10 }edge[2001]; 11 int head[1001],num,vis[1001],n; 12 ll size[1005],f[1005][1005],Mod=1e9+7,C[1005][1005],F[1005]; 13 void add(int x,int y,int w) 14 { 15 num++; 16 edge[num].next=head[x]; 17 edge[num].to=y; 18 head[x]=num; 19 edge[num].w=w; 20 } 21 void dfs(int x) 22 {int i,p1,p3; 23 size[x]=1;f[x][1]=1; 24 vis[x]=1; 25 for (i=head[x];i;i=edge[i].next) 26 { 27 int v=edge[i].to; 28 if (vis[v]) continue; 29 dfs(v); 30 memcpy(F,f[x],sizeof(F)); 31 memset(f[x],0,sizeof(f[x])); 32 if (edge[i].w==1) 33 { 34 for (p1=1;p1<=size[x];p1++) 35 for (p3=p1;p3<=p1+size[v]-1;p3++) 36 (f[x][p3]+=C[p3-1][p1-1]*C[size[x]+size[v]-p3][size[x]-p1]%Mod*F[p1]%Mod*(f[v][size[v]]-f[v][p3-p1]+Mod)%Mod)%=Mod; 37 } 38 else 39 { 40 for (p1=1;p1<=size[x];p1++) 41 for (p3=p1+1;p3<=p1+size[v];p3++) 42 (f[x][p3]+=C[p3-1][p1-1]*C[size[x]+size[v]-p3][size[x]-p1]%Mod*F[p1]%Mod*f[v][p3-p1]%Mod)%=Mod; 43 } 44 size[x]+=size[v]; 45 } 46 for (i=1;i<=size[x];i++) 47 (f[x][i]+=f[x][i-1])%=Mod; 48 } 49 int main() 50 {int T,i,x,y,j; 51 char ch; 52 scanf("%d",&T); 53 C[0][0]=1; 54 for (i=1;i<=1000;i++) 55 { 56 C[i][0]=1; 57 for (j=1;j<=i;j++) 58 C[i][j]=(C[i-1][j-1]+C[i-1][j])%Mod; 59 } 60 while (T--) 61 { 62 scanf("%d",&n); 63 memset(head,0,sizeof(head)); 64 memset(edge,0,sizeof(edge)); 65 memset(f,0,sizeof(f)); 66 memset(vis,0,sizeof(vis)); 67 num=0; 68 for (i=1;i<n;i++) 69 { 70 scanf("%d %c %d",&x,&ch,&y); 71 x++;y++; 72 add(x,y,ch=='<'); 73 add(y,x,ch=='>'); 74 } 75 dfs(1); 76 printf("%lld ",f[1][n]); 77 } 78 }