「AHOI / HNOI2018」毒瘤

題目

虛樹DP。

#include<bits/stdc++.h>
#define maxn 100050
#define mod 998244353
#define pb push_back
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;

int n,m,sx[maxn],ty[maxn],ont[maxn],vis[maxn],ar[maxn],sb[maxn];
vector<int>G[maxn];
struct node{
	int v,c[2][2];
};
vector<node>E[maxn];

int F[maxn],fa[maxn],f[maxn][2],cot[maxn],nf[maxn][2];
int Find(int u){ return !F[u] ? u : F[u] = Find(F[u]); }

void addtree(int x){
	if(!ont[x]) ar[++ar[0]] = x;
	ont[x] = 1;
	for(;x && !vis[x];x=fa[x])
		vis[x] = 1;
	if(x){
		if(!ont[x]) ar[++ar[0]] = x;
		ont[x] = 1;
	}
}

void dfs0(int u,int ff){
	fa[u] = ff;
	for(int v:G[u]) if(v^ff)
		dfs0(v,u);
}

void dfs1(int u,int ff){
	f[u][0] = 1 , f[u][1] = 1;
	for(int v:G[u]) if(v^ff){
		dfs1(v,u);
		f[u][0] = 1ll * f[u][0] * (f[v][0] + f[v][1]) % mod;
		f[u][1] = 1ll * f[u][1] * f[v][0] % mod;
	}
}

void dfs2(int u,int ff){
	cot[u] = ont[u];
	for(int v:G[u])
		if(v^ff)
			dfs2(v,u),cot[u] += cot[v];
}

void dfs3(int u,int ff){
	nf[u][0] = 1 , nf[u][1] = 1;
	for(int v:G[u]) if(v^ff && cot[v] == 0){
		dfs3(v,u);
		nf[u][0] = 1ll * nf[u][0] * (nf[v][0] + nf[v][1]) % mod;
		nf[u][1] = 1ll * nf[u][1] * nf[v][0] % mod;
	}
}

int banc[maxn][2],pf[maxn][2];

void dfs5(int u){
	pf[u][0] = nf[u][0];
	pf[u][1] = nf[u][1];
	for(auto v:E[u]){
		dfs5(v.v);
		pf[u][0] = 1ll * pf[u][0] * (1ll * v.c[0][0] * pf[v.v][0] % mod + 1ll * v.c[0][1] * pf[v.v][1] % mod ) % mod;
		pf[u][1] = 1ll * pf[u][1] * (1ll * v.c[1][0] * pf[v.v][0] % mod + 1ll * v.c[1][1] * pf[v.v][1] % mod ) % mod;
	}
//	printf("@%d %d %d\n",u,pf[u][0],pf[u][1]);
	if(banc[u][0]) pf[u][0] = 0;
	if(banc[u][1]) pf[u][1] = 0;
}

int ans ;
void dfs4(int u){
	if(u == m-n+2){
		dfs5(1);
		ans = (ans + 1ll * pf[1][0] + pf[1][1] ) % mod;
		return;
	}
	banc[sb[u<<1]][1]++;
	dfs4(u+1);
	banc[sb[u<<1]][1]--;
	
	banc[sb[u<<1]][0]++;
	banc[sb[u<<1|1]][1]++;
	dfs4(u+1);
	banc[sb[u<<1]][0]--;
	banc[sb[u<<1|1]][1]--;
}

int main(){
	scanf("%d%d",&n,&m);
	sb[++sb[0]] = 1;
	rep(i,1,m){
		scanf("%d%d",&sx[i],&ty[i]);
		if(Find(sx[i]) ^ Find(ty[i])){
			G[sx[i]].pb(ty[i]);
			G[ty[i]].pb(sx[i]);
			F[Find(sx[i])] = Find(ty[i]);
		}
		else{
			sb[++sb[0]] = sx[i],sb[++sb[0]] = ty[i];
		}
	}
	dfs0(1,0);
	rep(i,1,sb[0]) addtree(sb[i]);
	rep(i,1,ar[0]){
		if(ar[i] == 1) continue;
		int j=fa[ar[i]],pr=ar[i];
		f[pr][0] = 1 , f[pr][1] = 0;
		for(;!ont[j];j=fa[j],pr=fa[pr]){
			f[j][0] = f[j][1] = 1;
			for(int v:G[j]) if(v^fa[j]){
				if(v^pr) dfs1(v,j);
				f[j][0] = 1ll * f[j][0] * (f[v][0] + f[v][1]) % mod;
				f[j][1] = 1ll * f[j][1] * f[v][0] % mod;
			}
		}
		node p;p.v = ar[i],p.c[0][0]=(f[pr][0]+f[pr][1])%mod,p.c[1][0]=f[pr][0];
		j=fa[ar[i]],pr=ar[i];
		f[pr][0] = 0 , f[pr][1] = 1;
		for(;!ont[j];j=fa[j],pr=fa[pr]){
			f[j][0] = f[j][1] = 1;
			for(int v:G[j]) if(v^fa[j]){
				if(v^pr) dfs1(v,j);
				f[j][0] = 1ll * f[j][0] * (f[v][0] + f[v][1]) % mod;
				f[j][1] = 1ll * f[j][1] * f[v][0] % mod;
			}
		}
		p.c[0][1]=(f[pr][0]+f[pr][1])%mod,p.c[1][1]=f[pr][0];
		E[j].pb(p);
	}
	dfs2(1,0);
	rep(i,1,ar[0])
		dfs3(ar[i],fa[ar[i]]);
	dfs4(1);
	printf("%d\n",(ans+mod)%mod);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章