[HEOI2013]SAO
Posted skylee的OI博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[HEOI2013]SAO相关的知识,希望对你有一定的参考价值。
题目大意:
一个有向无环图上有n个结点,
现在告诉你n-1个条件(x,y),表示x和y的先后关系。
问原图共有几种可能的拓扑序?
思路:
树形DP。
f[i][j]表示对于第i个结点,有j个点在它前面的方案数。
设当前结点为x,后面有一个结点为y,原本x前有i个结点,y前有j个结点,我们可以得到状态转移方程:
f[x][size[x]-i+size[y]-j]+=f[x][size[x]-i]*c[i+j][i]*c[size[x]-i+size[y]-j][size[y]-j]*((sum[y][size[y]]-sum[y][size[y]-j]+mod)%mod);
其中c是预处理好的组合数,sum是f数组的前缀和。
同样对于y在x前面的情况,状态转移方程如下:
f[x][i+j]+=f[x][i]*c[i+j][i]*c[size[x]-i+size[y]-j][size[y]-j]*sum[y][j];
最后就是求f[root][0]~f[root][n-1]的和,也就是sum[root][n]。
1 #include<cstdio> 2 #include<cctype> 3 #include<vector> 4 #include<cstring> 5 typedef long long int64; 6 inline int getint() { 7 register char ch; 8 while(!isdigit(ch=getchar())); 9 register int x=ch^‘0‘; 10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^‘0‘); 11 return x; 12 } 13 const int N=1001,mod=1e9+7; 14 struct Edge { 15 int to; 16 bool type; 17 }; 18 std::vector<Edge> e[N]; 19 inline void add_edge(const int &u,const int &v,const bool &type) { 20 e[u].push_back((Edge){v,type}); 21 e[v].push_back((Edge){u,!type}); 22 } 23 int c[N][N]; 24 inline void prep() { 25 for(register int i=0;i<N;i++) { 26 c[i][0]=1; 27 for(register int j=1;j<=i;j++) { 28 c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod; 29 } 30 } 31 } 32 int f[N][N],sum[N][N],size[N]; 33 inline void init() { 34 memset(f,0,sizeof f); 35 for(register int i=0;i<N;i++) { 36 e[i].clear(); 37 } 38 } 39 void dp(const int &x,const int &par) { 40 size[x]=0; 41 f[x][0]=1; 42 for(unsigned i=0;i<e[x].size();i++) { 43 const int &y=e[x][i].to; 44 if(y==par) continue; 45 dp(y,x); 46 static int g[N]; 47 memset(g,0,sizeof g); 48 if(e[x][i].type) { 49 for(register int i=0;i<=size[x];i++) { 50 for(register int j=0;j<=size[y];j++) { 51 g[size[x]-i+size[y]-j] 52 +=(int64)f[x][size[x]-i] 53 *c[i+j][i]%mod 54 *c[size[x]-i+size[y]-j][size[y]-j]%mod 55 *((sum[y][size[y]]-sum[y][size[y]-j]+mod)%mod)%mod; 56 g[size[x]-i+size[y]-j]%=mod; 57 } 58 } 59 } else { 60 for(register int i=0;i<=size[x];i++) { 61 for(register int j=0;j<=size[y];j++) { 62 g[i+j] 63 +=(int64)f[x][i] 64 *c[i+j][i]%mod 65 *c[size[x]-i+size[y]-j][size[y]-j]%mod 66 *sum[y][j]%mod; 67 g[i+j]%=mod; 68 } 69 } 70 } 71 size[x]+=size[y]; 72 memcpy(f[x],g,sizeof g); 73 } 74 size[x]++; 75 for(register int i=1;i<=size[x];i++) { 76 sum[x][i]=(sum[x][i-1]+f[x][i-1])%mod; 77 } 78 } 79 int main() { 80 prep(); 81 for(register int T=getint();T;T--) { 82 init(); 83 const int n=getint(); 84 for(register int i=1;i<n;i++) { 85 const int u=getint(),sign=getchar(),v=getint(); 86 add_edge(u,v,sign==‘<‘); 87 } 88 dp(0,-1); 89 printf("%d\n",sum[0][n]); 90 } 91 return 0; 92 }
以上是关于[HEOI2013]SAO的主要内容,如果未能解决你的问题,请参考以下文章