[loj#2091] [ZJOI2016] 小星星

题意简述

给定一个 \(n\) 个点 \(m\) 条边的无向图,再给定一棵 \(n\) 个点的树。
要把树中的点与无向图中的点一一对应,要求树上有连边的点所对应的点在图上也有连边。
问有多少种对应方式。

\(n\leq 17\)


想法

首先,我觉得这题应有 \(bgm\)

你 就是我的小星星
挂 在那天上放光明
我已经决定要爱你
就不会轻易放弃

哒哒哒~

言归正传!
先考虑树形 \(dp\)\(f[i][j][s]\) 表示 \(i\) 与原图中 \(j\) 对应时,以 \(i\) 为根的子树与 \(s\) 中的点对应的方案数(\(s\) 为状压)
但这样过不去。

发现这里最麻烦的就是 \(s\) ,于是把它容斥掉。
\(g[s]\) 表示树上所有点只与 \(s\) 中的点对应的方案数。
在此\(s\) 下,\(f[i][j]\) 表示 \(i\) 与原图中 \(j\) 对应时,以 \(i\) 为根的子树与 \(s\) 中的点对应的方案数
有转移方程 \(f[i][j]=\prod\limits_{fa[v]=i} (\sum\limits_{j与k在原图中有边} f[v][k])\)
显然 \(g[s]=\sum\limits_{i\in s}f[root][i]\)

容斥很经典,\(ans=\sum(-1)^{n-|s|} \times g[s]\)


总结

树上问题,先考虑树形 \(dp\) !别先想那些奇奇怪怪的做法!
神仙容斥……


代码

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;

int read(){
	int x=0;
	char ch=getchar();
	while(ch<'0' || ch>'9') ch=getchar();
	while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}

const int N = 18;
typedef long long ll;

int mp[N][N],con[N][N],n,m;
struct node{
	int v;
	node *nxt;
}pool[N*2],*h[N];
int cnt;
void addedge(int u,int v){
	node *p=&pool[++cnt];
	p->v=v;p->nxt=h[u];h[u]=p;
}

ll f[N][N];
int fa[N];
void dfs(int u){
	for(int v=1;v<=n;v++)
		if(con[u][v] && !fa[v]) {
			fa[v]=u; addedge(u,v);
			dfs(v);
		}
}

int ok[N];
void cal(int u){
	int v;
	ll t;
	for(node *p=h[u];p;p=p->nxt) cal(p->v);
	for(int i=1;i<=n;i++){
		if(ok[i]^1) { f[u][i]=0; continue; }
		f[u][i]=1;
		for(node *p=h[u];p;p=p->nxt){
			v=p->v; t=0;
			for(int j=1;j<=n;j++) if(mp[i][j]) t+=f[v][j];
			f[u][i]*=t; 
		}
	}
}

int main()
{
	int u,v;
	n=read(); m=read();
	for(int i=0;i<m;i++){
		u=read(); v=read();
		mp[u][v]=mp[v][u]=1;
	}
	for(int i=1;i<n;i++) {
		u=read(); v=read();
		con[u][v]=con[v][u]=1;
	}
	
	fa[1]=-1; dfs(1);
	int w=(1<<n),t;
	ll ans=0,cur;
	for(int s=1;s<w;s++){
		t=0; cur=0;
		for(int i=0;i<n;i++) 
			ok[i+1]=(1&(s>>i)),t+=ok[i+1];
		cal(1);
		for(int i=1;i<=n;i++) cur+=f[1][i];
		ans+=cur*(((n-t)&1) ? (-1) : 1);
	}
	printf("%lld\n",ans);
	
	return 0;
}
posted @ 2020-03-03 21:31  秋千旁的蜂蝶~  阅读(121)  评论(0编辑  收藏  举报