挺弱智的题 但是我不会
首先从一个叶子开始考虑,如果这个叶子是白的那么就应该先选它,否则就应该先选它父亲。
然后这样我们可以递归着对子树进行计算,一些子树需要先选,一些子树需要后选,直接 DP 一下就能知道哪些点先选哪些点后选了。
然后我们从先选的向后选的连一条边,那么一个合法方案就是对这个 DAG 进行拓扑排序的过程,直接贪心的跑拓扑排序即可。
树上与它相邻的点有关系的题从叶子开始考虑,因为叶子只有一个相邻的点。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
int n;
vector<int> e[MAXN];
int deg[MAXN];
vector<int> e2[MAXN];
int col[MAXN];
char s[MAXN];
void dfs(int u, int pre) {
for (int v : e[u]) if (v != pre) {
dfs(v, u);
col[u] ^= col[v];
}
if (u != 1) {
if (col[u]) {
e2[u].push_back(pre);
deg[pre]++;
} else {
e2[pre].push_back(u);
deg[u]++;
}
}
}
int main() {
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
}
scanf("%s", s + 1);
for (int i = 1; i <= n; i++) {
col[i] = s[i] == 'W';
}
dfs(1, 0);
if (!col[1]) {
printf("-1\n");
return 0;
}
priority_queue<int, vector<int>, greater<int>> q;
for (int i = 1; i <= n; i++) {
if (!deg[i]) {
q.push(i);
}
}
while (!q.empty()) {
int u = q.top(); q.pop();
for (int v : e2[u]) {
deg[v]--;
if (!deg[v]) q.push(v);
}
printf("%d ", u);
}
printf("\n");
return 0;
}
标签:ARC143E,pre,int,Reversi,back,先选,解题,MAXN,col
From: https://www.cnblogs.com/apjifengc/p/17058298.html