洛谷 P10723 [GESP202406 七级] 黑白翻转-普及+/提高
题目描述
小杨有一棵包含 nnn 个节点的树,这棵树上的任意一个节点要么是白色,要么是黑色。小杨认为一棵树是美丽树当且仅当在删除所有白色节点之后,剩余节点仍然组成一棵树。
小杨每次操作可以选择一个白色节点将它的颜色变为黑色,他想知道自己最少要执行多少次操作可以使得这棵树变为美丽树。
输入格式
第一行包含一个正整数 nnn,代表树的节点数。
第二行包含 nnn 个非负整数 a1,a2,…,ana_1,a_2,\ldots,a_na1,a2,…,an,其中如果 ai=0a_i=0ai=0,则节点 iii 的颜色为白色,否则为黑色。
之后 n−1n-1n−1 行,每行包含两个正整数 xi,yix_i,y_ixi,yi,代表存在一条连接节点 xix_ixi 和 yiy_iyi 的边。
输出格式
输出一个整数,代表最少执行的操作次数。
输入输出样例 #1
输入 #1
5
0 1 0 1 0
1 2
1 3
3 4
3 5
输出 #1
2
说明/提示
样例解释
将节点 111 和 333 变为黑色即可使这棵树变为美丽树,此时删除白色节点 555,剩余黑色节点仍然组成一棵树。
数据范围
子任务编号 | 数据点占比 | nnn | aia_iai | 特殊条件 |
---|---|---|---|---|
111 | 30%30\%30% | ≤105\leq 10^5≤105 | 0≤ai≤10\leq a_i\leq 10≤ai≤1 | 树的形态为一条链 |
222 | 30%30\%30% | ≤105\leq 10^5≤105 | 0≤ai≤10\leq a_i\leq 10≤ai≤1 | 只有两个节点颜色为黑色 |
333 | 40%40\%40% | ≤105\leq 10^5≤105 | 0≤ai≤10\leq a_i\leq 10≤ai≤1 |
对于全部数据,保证有 1≤n≤1051\leq n\leq 10^51≤n≤105,0≤ai≤10\leq a_i\leq 10≤ai≤1。**
solution
采用拓扑排序的思路,逐步将白色叶子节点删除,剩余的白色节点则是答案
代码
#include <iostream>
#include "bit"
#include "vector"
#include "unordered_set"
#include "set"
#include "queue"
#include "algorithm"
#include "bitset"
#include "cstring"using namespace std;int n, x, y, cnt[100001];
char a[100001];
vector<int> e[100001];int main() {cin >> n;if(n == 1){cout << 0;return 0;}int s = 0;for (int i = 1; i <= n; i++) {cin >> a[i];s += a[i] == '0';}for (int i = 1; i < n; i++) {cin >> x >> y;e[x].push_back(y);e[y].push_back(x);cnt[x]++;cnt[y]++;}queue<int> q;for (int i = 1; i <= n; i++) {if (cnt[i] == 1 && a[i] == '0') {q.push(i);}}int t = q.size();while (!q.empty()) {int u = q.front();q.pop();for (int v: e[u]) {cnt[v]--;if(cnt[v] == 1 && a[v] == '0'){q.push(v);t++;}}}cout << s - t;
}