【题解】CF53E Dead Ends

0

EASY,完全独立开掉的紫题

1:数据范围

根据范围,考虑状压 \(DP\)

2:如何dp

如果 生成树集合终点集合 相同,则它们是等价的

把他们压成状态

3:怎么转移

\(dp[S][G]:\) 生成树集合为 \(S\) ,终点集合为 \(G\),方案数

枚举非 \(S\) 集合中的点,再枚举 \(S\) 集合中的点,保证他们之间连边

由此重新计算 \(S,G\) 得到 \(S1,G1\) ,进行转移

4:修正

我们测样例的时候,发现过不了

而输出是样例的若干倍数

我们画图观察得到结论:

如果 \(dp[S][G]\)\(G\)\(x\)\(1\) ,则 \(dp[S][G]\) 会被重复统计 \(x\) 次,需要除去

5:代码

#include<bits/stdc++.h>
using namespace std;
const int N=11;
int dp[1<<N][1<<N];
int mp[N][N];
int n,m,K;
int msiz(int x){
	int res=0;
	while(x){
		res+=x&1;
		x>>=1;
	}
	return res;
}
int main(){
	cin>>n>>m>>K;
	while(m--){
		int a,b;cin>>a>>b;
		a--;b--;
		mp[a][b]=mp[b][a]=1;
	}
	dp[0][0]=1;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(i==j) continue;
			if(mp[i][j]) dp[(1<<i)^(1<<j)][(1<<i)^(1<<j)]=2;
		}
	}
	for(int S=0;S<(1<<n);S++){
		for(int G=S;~G;G--){
			G&=S;
			if(dp[S][G]==0) continue;
			if(msiz(G)) dp[S][G]/=msiz(G);
			for(int i=0;i<n;i++){
				if(S>>i&1) continue;
				int S1=S^(1<<i);
				for(int j=0;j<n;j++){
					if(!mp[i][j]) continue;
					if(!(S>>j&1)) continue;
					int G1=G^(1<<i);
					if(G1>>j&1) G1^=(1<<j);
					dp[S1][G1]+=dp[S][G];
					//cout<<"-->"<<S<<" "<<G<<" "<<S1<<" "<<G1<<" "<<dp[S1][G1]<<"\n";
				}
			}
		}
	}
	int ans=0;
	for(int G=0;G<(1<<n);G++){
		if(msiz(G)==K){
			ans+=dp[(1<<n)-1][G];
			//cout<<(1<<n)-1<<" "<<G<<" "<<dp[(1<<n)-1][G]<<"\n";
		}
	}
	cout<<ans<<"\n";
	return 0;
}

6:反思

修正

posted @ 2026-06-26 15:35  Aistyr  阅读(5)  评论(0)    收藏  举报