其他分享
首页 > 其他分享> > Codeforces Round #630 -- F. Independent Set

Codeforces Round #630 -- F. Independent Set

作者:互联网

解法

我们将独立子集中的点叫做染色点。
题目其实就是在树上进行删边操作,使得没有相邻的染色点,且没有孤立的染色点。
考虑树DP。对于每个节点,有3种状态,染色了,没有被染色且与儿子节点有连边,没有被染色且与所有儿子节点没连边(也就是孤立节点)。
这样很容易进行转移
\(f[u][0]=\prod_{v} (f[v][0]+f[v][1]+f[v][2])\),这个点如果是孤立节点,就不和任何儿子连边,儿子状态也就任意
剩余两种也类似,考虑连边不连边,在容斥一下就行了。
需要注意的一点就是,在考虑当前节点不染色且与儿子连边的情况的时候,要考虑,这个节点和孤立儿子节点连边的话,是可以将儿子节点染色的。

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

const int maxn = 3e5;
const ll mol = 998244353;
ll f[maxn + 11][5];

vector <int> edge[maxn + 11];
ll add(ll a,ll b) { a += b; if (a >= mol) a -= mol; return a; }
ll sub(ll a,ll b) { a -= b; if (a < 0) a += mol; return a; }

void dfs(int x,int fa) {
	ll tmp[10];
	tmp[0] = tmp[1] = tmp[2] = 1;
	for (auto v : edge[x]) {
		if (v == fa) continue;
		dfs(v , x);
		tmp[0] = tmp[0] * add(add(f[v][0] , f[v][1]) , f[v][2]) % mol;
		tmp[1] = tmp[1] * add(add(3 * f[v][0] % mol , 2 * f[v][1] % mol) , 2 * f[v][2] % mol) % mol;
		tmp[2] = tmp[2] * add(add(2 * f[v][0] % mol , 2 * f[v][1] % mol) , f[v][2] % mol) % mol;
	}
	f[x][0] = tmp[0];
	f[x][1] = sub(tmp[1] , tmp[0]);
	f[x][2] = sub(tmp[2] , tmp[0]);
} 

int main(){ 
	int n; scanf("%d",&n);
	for (int i = 1; i < n; i++) {
		int u,v;
		scanf("%d %d",&u,&v);
		edge[u].push_back(v);
		edge[v].push_back(u);
	} 
	dfs(1 , 0);
	printf("%lld\n" , sub(add(add(f[1][0] , f[1][1]) , f[1][2]) , 1));
} 

标签:630,Independent,Set,int,ll,add,mol,tmp,节点
来源: https://www.cnblogs.com/Embiid/p/12615781.html