「解题报告」ARC143E Reversi

挺弱智的题 但是我不会

首先从一个叶子开始考虑,如果这个叶子是白的那么就应该先选它,否则就应该先选它父亲。

然后这样我们可以递归着对子树进行计算,一些子树需要先选,一些子树需要后选,直接 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;
}
posted @ 2023-01-17 17:05  APJifengc  阅读(39)  评论(2编辑  收藏  举报