2019牛客多校第五场 F maximum clique 1 状压dp+最大独立集
maximum clique 1
题意
给出一个集合s,求每个子集的最大独立集的权值和(权值是独立集的点个数)
分析
n比较小,一股浓浓的暴力枚举每一个子集的感觉,但是暴力枚举模拟肯定会T,那么想一想怎么优化复杂度,我们可以使用状压dp,对于一个集合,并且对于任意一个点,这个点要么不在该集合的最大独立集里面,要么在里面,如果在里面,那么所有和该点相邻的都不在,只需要取max就是算出dp[i],i集合的最大独立集,这里状态很明确,但是会随之发生疑问,为什么随机取一个点就可以?写的时候确实想了很久也证明了很久,但是比赛的时候,只要定义明确,不产生状态冲突,直接冲即可,毕竟不是数学题
这里要注意内存,不要超内存了
#include<bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define pii pair<int,int>
#define mkp make_pair
typedef long long ll;
using namespace std;
const int maxn=130;;
int mp[200];
char dp[1<<26];
int main(){
int n,m,x,y;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
mp[x]|=1<<y;
mp[y]|=1<<x;
}
int sum=0;
dp[0]=0;
for(int i=0;i<n;i++)mp[i]=~mp[i];
for(int i=1;i<(1<<n);i++){
x=i&(-i);
int flag=__builtin_ctz(x);
dp[i]=max(int(dp[i^x]),dp[(i^x)&(mp[flag])]+1);
sum+=dp[i];
}
cout<<sum<<endl;
return 0;
}