2019 牛客多校第5场 E independent set 1

题目链接:https://ac.nowcoder.com/acm/contest/885/E

又是一道水题没做,不过看题解时有地方想不太清楚。dp[i]表示i所代表的集合的最大独立子集的大小,随便从这个集合中取一个点x,dp[i]=max(dp[i^mi[x]],dp[i&e[x]]+1),e[x]表示与x都没有边的点的集合。之前想不太清楚为什么只要随便取一个点枚举。后来思考了一哈因为dp[i^mi[x]]是已经确定大小的,所以我们就只要考虑x丢不丢进i的最大独立集的集合中,丢进来,那么久只能是与x不相邻的那些店的最大独立子集的大小+1了。枚举别的点,和枚举x是等效的,因为在求dp[i^mi[x]]时,已经枚举了其他点,从小到大枚举,只要保证前面是对的,推到后面肯定是对的。。。完了这么水的dp也开始要想很久才能想清楚了。

#include<bits/stdc++.h>
using namespace std;

int n,m,sum;
int e[27],mi[27];
char dp[1<<26];

inline void prework()
{
	scanf("%d%d",&n,&m);
	int u,v;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		e[v]|=(1<<u);
		e[u]|=(1<<v);
	}
	mi[0]=1;
	for(int i=1;i<=n;i++)
		mi[i]=mi[i-1]*2;
	int s=(1<<n)-1;
	for(int i=0;i<n;i++)
		e[i]=s^(e[i]|mi[i]);
}

inline void mainwork()
{
	int s=(1<<n)-1;
	int x,id;
	for(int i=1;i<=s;i++)
	{
		x=i&-i;id=log2(x);
		dp[i]=max(dp[i^x],(char)(dp[i&e[id]]+1));
		sum+=dp[i];
	}
}

inline void print()
{
	printf("%d",sum);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值