• BZOJ 4455: [Zjoi2016]小星星


    题面:求一棵树嵌入一张图里有多少种不同的方案数

    题解:首先是一个树形DP。dp[x][s]表示以x为根的子树使用了s这个集合。然而发现这个转移要枚举子集,复杂度好像很高的样子,我也不知道加了神奇的优化能不能过去。

    然后我们发现如果一个数可以同时对应多个数就可以避免枚举子集,现在假设不用一一对应,状态就变成了dp[x][s]表示x这个点对应了s这个点,然后转移的话只要枚举它儿子对应着哪个点就行了。

    然而我们发现这样计算会多出不合法的方案来,所以考虑用容斥。减去有一个点没被用过的方案数,加上两个点没被用过的方案数......。首先枚举哪些点用了,然后进行DP。由于避免了枚举子集,所以复杂度从3^n*n^2变成了2^n*n^3。然后只要不写得太暴力应该都能过去的。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int n,m,cnt,num,map[1005][1005],last[1000005],a[1000005],b[1000005];
    long long f[18][18],ans;
    struct node{
    	int to,next;
    }e[1000005];
    void add(int a,int b){
    	e[++cnt].to=b;
    	e[cnt].next=last[a];
    	last[a]=cnt;
    }
    void dp(int x,int fa){
    	for (int i=1; i<=num; i++) f[x][i]=1;
    	for (int i=last[x]; i; i=e[i].next){
    		int V=e[i].to;
    		if (V==fa) continue;
    		dp(V,x);
    		for (int c=1; c<=num; c++){
    			long long sum=0;
    			for (int d=1; d<=num; d++) if (map[b[c]][b[d]]) sum+=f[V][d];
    			f[x][c]*=sum;
    		}
    	}
    }
    void dfs(int t,int ss){
    	if (t>n){
    		num=0;
    		for (int i=1; i<=n; i++)
    			if (a[i]) b[++num]=i;
    		for (int i=1; i<=num; i++)
    			for (int j=1; j<=num; j++)
    				f[i][j]=0;
    		dp(1,0);
    		for (int i=1; i<=num; i++) ans+=1ll*ss*f[1][i];
    		return;
    	}
    	a[t]=0;
    	dfs(t+1,-ss);
    	a[t]=1;
    	dfs(t+1,ss);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1; i<=m; i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		map[x][y]=map[y][x]=1;
    	}
    	for (int i=1; i<n; i++){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);
    		add(y,x);
    	}
    	dfs(1,1);
    	printf("%lld
    ",ans);
    	return 0;
    } 
    

      

  • 相关阅读:
    2.2 Scala基础知识
    Linux---用户及权限管理类命令
    Linux---进程控制类命令
    Linux---vim编辑文本文件
    Linux---文件压缩与解压缩命令
    Linux---查找命令
    Linux---基本目录与文件命令
    nginx配置技巧汇总
    Go 内嵌静态资源
    go语言的time.Sleep
  • 原文地址:https://www.cnblogs.com/silenty/p/8721461.html
Copyright © 2020-2023  润新知