[USACO16OPEN]Closing the Farm 题解

本题有两道一模一样的题目,改个数据范围即可 AC。

题目1 | 题目2

题意简述

给定一张无向图,每次删去一个点,问每次操作后图是否联通。

分析

判断图是否联通可以想到使用并查集来维护。但是并查集很难实现删除操作,那如何处理呢?

并查集的核心是“并”和“查”,既然题目要求每次删去一个点,那不如反过来想,倒序处理,把删点变成加点,这样处理起来就非常方便快捷了。

代码实现

#include <bits/stdc++.h>
using namespace std;
int n, m;

struct edge
{
    int to, nxt;
}e[3005 << 1];
int head[3005];
int idx;
void link(int x, int y) {
    e[++idx].to = y;
    e[idx].nxt = head[x];
    head[x] = idx;
}
int fa[3005];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

int del[3005];
int f[3005];

int main() {
    cin >> n >> m;
    for (int i = 1, x, y; i <= m; i++) {
        cin >> x >> y;
        link(x, y);
        link(y, x);
    }
    for (int i = 1; i <= n; i++)cin >> del[i];
    int cnt = 0;
    for (int i = n; i >= 1; i--) {
        int cur = del[i];
        fa[cur] = cur;
        cnt++;
        for (int j = head[cur]; j; j = e[j].nxt) {
            int v = e[j].to;
            if (fa[v]) {
                int x = find(v), y = find(cur);
                if (x != y) {
                    fa[x] = y;
                    cnt--;
                }
            }
        }
        if (cnt == 1)f[i] = true;
    }
    for (int i = 1; i <= n; i++)puts(f[i] ? "YES" : "NO");
    return 0;
}

练习

可以尝试做做 星球大战

上一篇:静态栈模板


下一篇:所反射企鹅