6566. 【GDOI2020模拟】图 (graph)

题目描述

有一张 n 个点,m 条边的无向图,你想选出一个非空点集,使得仅保留这个点集中的点和两个端点都在这个点集里的边后得到的图
是连通的。你想知道有多少种可能的选点集的方案。
由于出题人不是毒瘤,所以本题不对 998244353 取模,改为对2 取模。

题解

上次集训的杂题,但是我记不住啊

从模2下手,黑白染色维护(2^块数)的和模4

这样如果只有一块的话会被算2,否则不会计入

又发现|ai-bi|<=12,所以直接维护12个来状压黑白不选即可,要考虑当前点连边对应点的颜色

注意如果全不选的话是2^0=1要减掉

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
#define file
using namespace std;

int f[51][531441],p[13],n,m,i,j,k,l,ans,tot;
bool a[51][51];

void dg(int T,int t,int s,int S,int tp)
{
	int i;
	
	if (t>T)
	{
		f[T+1][S]=(f[T+1][S]+f[T][s])%4;
		if (tp!=-1)
		{
			fo(i,1,2)
			if (!tp || tp==i)
			f[T+1][S+i]=(f[T+1][S+i]+f[T][s])%4;
		}
		
		return;
	}
	
	dg(T,t+1,s,S,tp);
	fo(i,1,2)
	{
		if (T-t+1<12)
		dg(T,t+1,s+p[T-t+1]*i,S+p[T-t+2]*i,a[t][T+1]?(i!=tp?(!tp?i:-1):tp):tp);
		else
		dg(T,t+1,s+p[T-t+1]*i,S,a[t][T+1]?(i!=tp?(!tp?i:-1):tp):tp);
	}
}

int main()
{
	freopen("graph.in","r",stdin);
	#ifdef file
	freopen("graph.out","w",stdout);
	#endif
	
	scanf("%d%d",&n,&m);
	fo(i,1,m)
	scanf("%d%d",&j,&k),a[j][k]=a[k][j]=1;
	p[1]=1;fo(i,2,12) p[i]=p[i-1]*3;
	
	f[0][0]=1;
	fo(i,0,n-1)
	dg(i,max(i-11,1),0,0,0);
	
	fo(i,0,p[12]*3-1)
	ans=(ans+f[n][i])%4;
	printf("%d\n",((ans+3)%4)/2);
	
	fclose(stdin);
	fclose(stdout);
	
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/gmh77/p/12758000.html