[ARC101E]Ribbons on Tree

题意:一棵$n$个点的树($n$是偶数),把所有点分成$\frac n2$对,每对点都在树上路径涂色,问有多少种配对方式使得所有边都被涂上颜色

考虑容斥,设$E$是整棵树的边集,$F\subseteq E$,定义$f(F)$表示有多少种配对满足$F$中的边都不被涂色,那么答案是$\sum\limits_{F\subseteq E}(-1)^{|F|}f(F)$

对于一个给定的$F$,我们容易计算$f(F)$:设删去$F$中边后形成的$|F|+1$个连通块的大小为$n_{1\cdots|F|+1}$,那么$f(F)=\prod\limits_{i=1}^{|F|+1}g(n_i)$,其中$g(n)=[2|n](n-1)!!$

现在我们要求所有的$f(F)$,考虑DP

设$f_{i,j,k}$表示在$i$的子树中,删边数奇偶性为$k$,$i$所在连通块大小为$j$的配对方案数,注意这里的方案数是不管$i$所在连通块是如何配对的,即答案为$\sum\limits_{i=1}^n(f_{root,i,0}-f_{root,i,1})g_i$

转移就很自然了,枚举子树,按当前边删不删进行转移,时间复杂度$O(n^2)$

#include<stdio.h>
#include<string.h>
typedef long long ll;
const int mod=1000000007;
int mul(int a,int b){return(ll)a*b%mod;}
int ad(int a,int b){return(a+b)%mod;}
void inc(int&a,int b){(a+=b)%=mod;}
int h[5010],nex[10010],to[10010],M;
void add(int a,int b){
	M++;
	to[M]=b;
	nex[M]=h[a];
	h[a]=M;
}
int siz[5010],f[5010][5010][2],g[5010],p[5010][2];
void dfs(int fa,int x){
	int i,j,k,t1,t2;
	siz[x]=1;
	f[x][1][0]=1;
	for(i=h[x];i;i=nex[i]){
		if(to[i]!=fa){
			dfs(x,to[i]);
			memset(p,0,sizeof(p));
			for(j=1;j<=siz[x];j++){
				for(k=1;k<=siz[to[i]];k++){
					t1=ad(mul(f[x][j][0],f[to[i]][k][0]),mul(f[x][j][1],f[to[i]][k][1]));
					t2=ad(mul(f[x][j][0],f[to[i]][k][1]),mul(f[x][j][1],f[to[i]][k][0]));
					//connect
					inc(p[j+k][0],t1);
					inc(p[j+k][1],t2);
					//remove
					inc(p[j][0],mul(g[k],t2));
					inc(p[j][1],mul(g[k],t1));
				}
			}
			siz[x]+=siz[to[i]];
			memcpy(f[x],p,sizeof(p));
		}
	}
}
int main(){
	int n,i,x,y,s;
	scanf("%d",&n);
	for(i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	g[0]=1;
	for(i=2;i<=n;i+=2)g[i]=mul(g[i-2],i-1);
	dfs(0,1);
	s=0;
	for(i=2;i<=n;i+=2)inc(s,mul(g[i],f[1][i][0]-f[1][i][1]));
	printf("%d",ad(s,mod));
}

转载于:https://www.cnblogs.com/jefflyy/p/9569513.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值