首页 > 其他分享 >洛谷_[P4084]Barn Painting G题解

洛谷_[P4084]Barn Painting G题解

时间:2023-08-18 22:22:31浏览次数:53  
标签:cnt 洛谷 int 题解 add 100010 Painting col dp

题目链接
这题我们可以定义一个二维的 dp 数组,
在 dp[i][j]中:
i 表示对于节点 i,
j 有 1,2,3 三种状态,
表示当点 i 选择被染成颜色 j 时,以 i 为根的这颗子树有多少种染色方法。
那么根据乘法原理,节点 i 的方案数肯定等于 i 的每个儿子的方案数量之积。
这道题整个挺简单的,剩下细节的部分直接看下面的代码吧,(里面有详细注释):

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define mod 1000000007
int cnt = 0,head[100010],dp[100010][4],col[100010];
// dp 数组的意思就是我前面说的,col 数组用于记录该节点是不是提前被染成了什么颜色

struct Node
{
	int to,nex;
}e[200010];

void add(int x,int y)
{
	cnt++;
	e[cnt].to = y;
	e[cnt].nex = head[x];
	head[x] = cnt;
}

void dfs(int x,int fa)
{
	dp[x][1] = dp[x][2] = dp[x][3] = 1; // 因为后续要乘,所以默认初值是 1
	if(col[x] != 0) // 如果 x 本身有颜色
	{
		for(int i = 1; i <= 3; i++)
		{
			if(i != col[x])
				dp[x][i] = 0; // 那么这个节点不可能染成其他颜色
		}
	}
	bool flag = false; // 用于判断 x 是不是叶节点
	bool vis[4];
	vis[1] = vis[2] = vis[3] = false; // vis[i] 用于记录 x 的子树中有没有初始就染成颜色 i 的
	for(int i = head[x]; i; i = e[i].nex) // 前向星遍历
	{
		int y = e[i].to;
		if(y == fa) // 我们不能通过 x 又回到它的父节点去了
			continue;
		flag = true; // x 不是叶子节点
		if(col[y] != 0) // 如果 y 自带颜色
			vis[col[y]] = true; // 标记这种颜色
		dfs(y,x); // 进入这个儿子的 dfs
		if(col[x] != 0)
		{
			int tmp = 0;
			for(int j = 1; j <= 3; j++)
			{
				if(j == col[x]) // 如果 x 本身有颜色,则不能统计儿子中和它染成一样的颜色的方案
					continue;
				tmp += dp[y][j];
			}
			dp[x][col[x]] *= tmp; // 乘法原理
			dp[x][col[x]] %= mod;
		}
		else // 如果 x 本身没颜色,就没限制
		{
			// x 的子树不能染和它一样的颜色
			dp[x][1] *= dp[y][2] + dp[y][3];
			dp[x][1] %= mod;
			dp[x][2] *= dp[y][1] + dp[y][3];
			dp[x][2] %= mod;
			dp[x][3] *= dp[y][1] + dp[y][2];
			dp[x][3] %= mod;
		}
	}
	dp[x][1] %= mod;
	dp[x][2] %= mod;
	dp[x][3] %= mod;
	for(int i = 1; i <= 3; i++)
	{
		if(vis[i]) // 如果儿子中有这种颜色,则 x 不能染成这个颜色
			dp[x][i] = 0;
	}
}

signed main()
{
	int n,k;
	cin >> n >> k;
	for(int i = 1; i < n; i++)
	{
		int x,y;
		cin >> x >> y;
		add(x,y);
		add(y,x);
	}
	for(int i = 1; i <= k; i++)
	{
		int b,c;
		cin >> b >> c;
		col[b] = c;
	}
	dfs(1,-1); // 随便从哪个点开始,只不过我选的是 1 号点
	cout << (dp[1][1] + dp[1][2] + dp[1][3]) % mod << "\n"; // 最终答案是根节点染成颜色 1、2、3的方案数之和
	return 0;
}

记录
感谢阅读!求支持

标签:cnt,洛谷,int,题解,add,100010,Painting,col,dp
From: https://www.cnblogs.com/cookiebread/p/P4084.html

相关文章

  • 2023年 8月15日普及组南外集训题解
    A陷阱我们可以从\(l\)枚举到\(d\),再计算是否满足要求,满足要求加入到数组中,输出第一个和最后一个#include<iostream>usingnamespacestd;constintN=1e5+5;intk;intnums[N];intmain(){intl,d,x;cin>>l>>d>>x;for(inti=l;i<=d......
  • CF1806E 题解
    题目大意给你一棵树,然后定义一个函数$f(x,y)$,接下来给你$q$组询问\(x_{i},y_{i}\),让你求每一次的$f(x_{i},y_{i})$。分析首先我们尝试根据这个函数的定义暴力求值,代码实现如下。llBFquery(intg,inth){if(!g)return0;return1ll*a[g]*a[h]+BFquery(p......
  • P4005题解
    闲来无事写篇题解题面传送门简要题意一条线段上有\(n\)个点成对连接,求所连的线最小交点数。思路看到题目中\(n\le44\)自然想到最终复杂度大约在\(O(2^\frac{n}{2})\)左右。经过思考不难发现不论如何两地铁站之间有且只有以下八种方式进行连接:显然可以暴搜解决,......
  • wsl2 下输出重定向至 clip.exe 出现中文乱码问题解决方案
    背景win10系统在wls2下安装neovim后希望与windows剪切板通信。按教程添加如下配置。--系统剪切板ifvim.fn.has('wsl')then vim.g.clipboard={ name='WslClipboard', copy={ ['+']='clip.exe', ['*']='clip.exe'......
  • 搭配买卖题解
    原题题目描述joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n多云,云朵被编号为1,2,……,n,并且每朵云都有一个价值。但商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这多云有搭配的云都要买。但是Joe的钱有限,所以他希望买的价值越多越好。输入第1行:n、m、w,表示......
  • 「BJWC2012」冻结题解
    「BJWC2012」冻结题解一.题目"我要成为魔法少女!""那么,以灵魂为代价,你希望得到什么?""我要将有关魔法和奇迹的一切,封印于卡片之中"在这个愿望被实现以后的世界里,人们享受着魔法卡片(SpellCard,又名符卡)带来的便捷。现在,不需要立下契约也可以使用魔法了!你还不来试一试?比如,我们在......
  • [AGC004D] Teleporter 题解
    简单贪心。思路可以发现一号节点必然连向自己。由于题目中保证了最初每个点都可以到达一号节点。那么我们发现改完一后,原图变成了一棵十分优美的树。考虑在树上进行贪心。我们贪心的从叶子结点往上走。知道第\(k\)个若还没要到\(1\),就直接连向一号节点。这个贪心也比较......
  • 【题解】#119. 最大整数 题解(2023-07-12更新)
    #119.最大整数题解本文章的访问次数为次。Part1提示题目传送门欢迎大家指出错误并私信这个蒟蒻欢迎大家在下方评论区写出自己的疑问(记得@这个蒟蒻)本文已同步至学校网站、博客园。Part2背景本来是不想写这篇题解的,但是由于卡了这个蒟蒻\(1\)整天,故此纪念。Par......
  • CF1575G GCD Festival 题解
    题意给定一个长度为\(n\)的正整数数列\(a\),求\[\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\gcd\left(a_i,a_j\right)\times\gcd\left(i,j\right)\](\(1\len,a_i\le10^5\))。题解根据欧拉函数的性质,可以得出\[n=\sum\limits_{d\midn}\varphi(d)\]该......
  • [AT_ABC106_C]题解(C++)
    PartIPreface原题目\(\text{(Luogu)}\)原题目\(\text{(AtCoder)}\)PartIISketch给定一个字符串\(s\)以及一个整数\(k\)。该字符串为纯数字串。其中的数字\(x\)会在\(k\)天后变为\(x^{k-1}\)个\(x\)。求出\(10^{15}\)天后,串\(s\)的第\(k\)位是什么......