zoukankan      html  css  js  c++  java
  • UOJ#185. 【ZJOI2016】小星星 容斥原理 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ185.html

    题解

    首先暴力DP是 $O(3^nn^3)$ 的,大家都会。

    我们换个方向考虑。

    假设我们求的是树上每一个节点到图上的节点的映射,而且图上的一个点可以被树上多个点映射到,那么就是求图上所有点都被映射到至少一次的方案数。

    我们发现保证所有点都被映射到会很麻烦,所以我们考虑容斥。

    枚举哪些点一定没有被映射到,答案就是至少0个点没被映射到的 - 至少1个点的 + 至少2个点的 ……

    已经确定哪些点没有被映射到之后就好办了,设 $dp[i][j]$ 表示树上节点 $i$ 对应图上节点 $j$ 时,子树 $i$ 的方案数。

    转移比较容易想到,不说了。

    时间复杂度 $O(2^n n^3)$ 。

    代码

    #include <bits/stdc++.h>
    #define clr(x) memset(x,0,sizeof (x))
    using namespace std;
    typedef long long LL;
    LL read(){
    	LL x=0,f=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		f|=ch=='-',ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return f?-x:x;
    }
    const int N=20;
    int n,m;
    vector <int> e[N];
    int g[N][N],f[N];
    LL dp[N][N];
    int cnt1(int x){
    	int ans=0;
    	while (x)
    		x-=x&-x,ans++;
    	return ans;
    }
    void dfs(int x,int pre){
    	for (int i=1;i<=n;i++)
    		if (!f[i])
    			dp[x][i]=1;
    	for (auto y : e[x])
    		if (y!=pre){
    			dfs(y,x);
    			for (int i=1;i<=n;i++)
    				if (!f[i]){
    					LL tot=1;
    					for (int j=1;j<=n;j++)
    						if (!f[j]&&g[i][j])
    							tot+=dp[y][j];
    					dp[x][i]*=tot;
    				}
    		}
    }
    int main(){
    	n=read(),m=read();
    	for (int i=1;i<=m;i++){
    		int x=read(),y=read();
    		g[x][y]=g[y][x]=1;
    	}
    	for (int i=1;i<n;i++){
    		int x=read(),y=read();
    		e[x].push_back(y);
    		e[y].push_back(x);
    	}
    	LL ans=0;
    	for (int i=0;i<(1<<n);i++){
    		clr(f);
    		LL c=(cnt1(i)&1)?-1:1;
    		for (int j=0;j<n;j++)
    			if (i>>j&1)
    				f[j+1]=1;
    		clr(dp);
    		dfs(1,0);
    		for (int j=1;j<=n;j++)
    			ans+=c*dp[1][j];
    	}
    	cout<<ans<<endl;
    	return 0;
    }
    

      

  • 相关阅读:
    动态规划问题
    神经网络学习总结第二天
    神经网络学习第一天总结
    解决Python2.7的UnicodeEncodeError: ‘ascii’ codec can’t encode异常错误
    IntelliJ IDEA 历史版本下载地址
    第九章 数据查询基础
    第八章 用SQL语句操作数据
    第七章 用表组织数据
    第六章 程序数据库集散地:数据库
    linux文件或文件夹常见操作,排查部署在linux上程序问题常用操作
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ185.html
Copyright © 2011-2022 走看看