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;
}
posted @ 2019-08-25 00:14  tttttttttrx  阅读(139)  评论(0编辑  收藏  举报