BZOJ 1130 POI2008 POD Subdivision of Kingdom DFS

题目大意:给定一个n个点的无向图,要求将点集分成大小相等的两个子集,使两个子集之间的边数最少

n<=26,直接C(26,13)枚举也只有1000W(其实去掉重复的只有500W,我写代码时脑残忘去掉了)

但是常规的枚举方法每次需要O(n)统计答案,显然会T

这里我们考虑搜索

初始令S集为空,T集包含全部的点,然后依次枚举T的某个点加入S集

这个点加入S集时,与S集的连边需要从答案中扣除,与T集的连边需要加入答案

因此我们将一个点连出的所有边用一个二进制数表示 那么取交集就是连边的数量

预处理一下每个数的二进制表示有多少位即可

P.S. 我一开始预处理了[0,2^26)的位数,结果数组太大BZ上T到死,交到Main上直接MLE

因此我们预处理[0,2^13)的位数,然后把那个[0,2^26)之间的数拆成两半即可

时间复杂度O(C(n,n/2))

#include 
#include 
#include 
#include 
#define M 30
using namespace std;
int n,m,a[M];
char digit[1<<13];
int ans=0x3f3f3f3f,ans_sta;
int Digit(int x)
{
	return digit[x&(1<>n/2];
}
void DFS(int now,int pos,int sta,int cnt)
{
	if(now==n/2)
	{
		if(cnt>n>>m;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		a[x]|=(1<>1);i++)
		digit[i]=digit[i>>1]+(i&1);
	DFS(0,1,0,0);
	for(i=1;i<=n;i++)
		if(ans_sta&(1<


你可能感兴趣的:(DFS,BZOJ)