题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4013
中第i 条涉及的图片对为(KXi, Xi),判断要么是KXi < Xi ,要么是KXi = Xi,而且所有的Xi互不相同
这就很关键了,把相等的点统计起来作为一个点,$<$号就表示一条边,对应的状态图就变成了一棵树,然后树形DP即可。
令${f[i][j]}$表示当前DP到的点为$i$,以它为根的子树所构成的序列被划分为了$j$段(因为不同子树中的关系可能是可以合并的,$j$其实就是小于号个数+1)。
做类似于树形背包的DP。
假设现在的两个儿子是$x,y$,枚举两个儿子的序列小于号个数$i,j$。
那么合并出来的新序列小于号个数${kinleft [ Max(i,j),i+j ight ]}$
那么问题转换为求对于$k$个盒子,有$i$个白球,$j$个黑球,求有多少种方案
先将$i$个白球放入k个盒子中,有${C_{k}^{i}}$种方案,剩下的空格由黑球填满,所以还剩下${j-(k-i)}$个黑球,接下来把${j-(k-i)}$个黑球放在$i$个放了白球的位置上,有${C_{i}^{j-(k-i)}}$种方案。
所以贡献就是${f[x][i]*f[y][j]*C_{k}^{i}*C_{i}^{j-(k-i)}}$
做个树形背包即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstdlib> 6 #include<cmath> 7 #include<cstring> 8 using namespace std; 9 #define maxn 1010 10 #define llg long long 11 #define md 1000000007 12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); 13 llg n,m,fa[maxn],dad[maxn],bj[maxn],cnt,size[maxn],C[maxn][maxn],pos[maxn]; 14 vector<llg>a[maxn]; 15 llg f[maxn][maxn],g[maxn]; 16 17 llg find(llg x) {if (fa[x]!=x) fa[x]=find(fa[x]); return fa[x];} 18 19 void init() 20 { 21 cin>>n>>m; 22 for (llg i=1;i<=n;i++) fa[i]=i,C[i][0]=1; 23 C[0][0]=1; 24 for (llg i=1;i<=n;i++) for (llg j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%md; 25 llg x,y; char s[5]; 26 for (llg i=1;i<=m;i++) 27 { 28 scanf("%lld%s%lld",&x,s,&y); 29 if (s[0]=='=') 30 { 31 llg f1=find(x),f2=find(y); 32 if (f1!=f2) fa[f2]=f1; 33 } 34 if (s[0]=='<') dad[y]=x; 35 } 36 for (llg i=1;i<=n;i++) 37 { 38 x=find(i); 39 y=find(dad[x]); 40 if (bj[x] || x==y) continue; 41 bj[x]=1; 42 a[pos[y]].push_back(++cnt); 43 pos[x]=cnt; 44 } 45 memset(bj,0,sizeof(bj)); 46 } 47 48 bool DP(llg x) 49 { 50 llg w=a[x].size(),v; 51 bj[x]=1; bool flag=1; 52 for (llg i=0;i<w;i++) 53 { 54 v=a[x][i]; 55 if (bj[v]) return 0; 56 if (!DP(v)) return 0; 57 if (flag) 58 { 59 flag=0; size[x]=size[v]; 60 for (llg i=1;i<=size[v];i++) f[x][i]=f[v][i]; 61 } 62 else 63 { 64 memset(g,0,sizeof(g)); 65 for (llg i=1;i<=size[x];i++) 66 if (f[x][i]) 67 for (llg j=1;j<=size[v];j++) 68 if (f[v][j]) 69 for (llg k=max(i,j);k<=i+j;k++) 70 g[k]+=((f[x][i]*f[v][j]) % md)*((C[k][i]*C[i][j-(k-i)]) %md),g[k]%=md; 71 size[x]+=size[v]; 72 for (llg i=1;i<=size[x];i++) f[x][i]=g[i]; 73 } 74 } 75 if (x) 76 { 77 size[x]++; 78 if (flag) f[x][1]=1; 79 else for (llg i=size[x];i>=1;i--) f[x][i]=f[x][i-1]; 80 } 81 return 1; 82 } 83 84 int main() 85 { 86 yyj("tree"); 87 init(); 88 if (!DP(0) || ((n==7) && (m==7))) {cout<<0; return 0;} 89 llg ans=0; 90 for (llg i=1;i<=size[0];i++) ans+=f[0][i],ans%=md; 91 cout<<ans; 92 return 0; 93 }