题解 P5157 【[USACO18DEC]The Cow Gathering】

· · 题解

简化题意

简化为给定一棵大小为n的树, 有m个限制

问每次删除一个叶子节点, 可能最后留下的点的集合

分析

nice problem

不难发现: 如果没有限制, 那么所有的点都可行...

首先, 我们可以贪心先找出一个可行点, 解决方法如下

每次寻找一个没有限制条件的叶子节点删去 重复上述操作, 最后的节点即为可行答案之一 若不成功, 则视为无解

Prove

于是证明了该方法是可以找出合法点以及判断无解的!

sol

先提供一个O(n^2)的做法:

那么会发现一个trick:

这样就可以搞事情了

我们既然已经找出了一个可行解(记为rt)

那么可以发现所有的可行解必定都是一起的, 一遍dfs即可...

复杂度: O(n)

Code

// Made by Bar.
#include <bits/stdc++.h>
using namespace std;

namespace {
    template <typename T> inline void read(T &x) {
        x = 0; T f = 1; char c = getchar();
        for(; !isdigit(c); c = getchar())
            if(c == '-') f = -1;
        for(;  isdigit(c); c = getchar())
            x = (x << 3) + (x << 1) + (c ^ 48);
        x *= f;
    }
}

const int N = 1E5 + 50;

int n, m, rt, d[N], vis[N], ans[N];
vector<int> g[N], l[N];
queue<int> que;

int cnt;
int solve(int cnt = 0) {
    for(; !que.empty(); ) {
        int u = que.front(); que.pop();
        ++ cnt;
        if(d[u] != 1) {
            if(d[u] < 1) return u;
            for(int i = 1; i <= n; ++i) printf("0\n");
            exit(0);
        } 
        for(auto v : g[u]) {
            -- d[v]; ++ cnt;
            if(d[v] == 1) que.push(v);
        }
        for(auto v : l[u]) {
            -- d[v]; ++ cnt;
            if(d[v] == 1) que.push(v);
        }
    }
    if(cnt != n) {
        for(int i = 1; i <= n; ++i) printf("0\n"); 
        exit(0);
    }
}
void dfs(int u, int fa = -1) {
    ans[u] = 1;
    for(auto v : g[u]) 
        if(v != fa && !vis[v]) 
            dfs(v, u);
}
int main() {
    read(n), read(m);
    for(int u, v, i = 1; i < n; ++i) {
        read(u), read(v);
        g[u].push_back(v), g[v].push_back(u); 
        ++ d[u], ++ d[v];
    }
    for(int a, b, i = 1; i <= m; ++i) {
        read(a), read(b);
        l[a].push_back(b);
        ++ d[b];
        vis[a] = true;
    }
    for(int i = 1; i <= n; ++i) 
        if(d[i] == 1) que.push(i);
    rt = solve();
    dfs(rt);
    for(int i = 1; i <= n; ++i)
        printf("%d\n", ans[i]);
    return 0;
}