【并查集-判环】Is It A Tree? POJ

Is It A Tree? POJ - 1308

小希的迷宫 HDU - 1272

题意:

这两题几乎一样,代码改一下输出就行了。

给定一个图,判断这个图是不是树。

思路:

这里判定标准有三个:一是无环,二是n个结点,n-1条边,三是空树的情况。

后两个条件很简单,统计一下就可以了;至于判环,可以用到并查集。

将存在通路(直接或间接)的结点(u)(v)视为在同一个集合内,则可以将一条边的两个端点并在一起。如存在边(0→1)及边(1→2),则(0)(1)(2)并入同一个集合,然后再有边(0→2),又(0)(2)已经属于同一集合,也就是说,加入这条边之后会构成回路,即当find(u)==find(v)时,图中存在环。

int fa[maxn];

int find(int x) {
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void merge(int x, int y) {
    fa[x] = y;
    //因为在merge函数之前已经find过并比较了,以下均可省略
    /*
    int fx = find(x);
    int fy = find(y);
    if (fx != fy) fa[fy] = fx;
    */
}

int main()
{
    //ios::sync_with_stdio(false);
    int n, m;
    int kase = 0;
    int ok = 1;
    int edge = 0;
    set<int> s;
    for (int i = 1; i < maxn; i++) fa[i] = i;
    while (cin >> n >> m) {
        if (n == -1 && m == -1) break;
        if (!(!n && !m)) {
            s.insert(n);
            s.insert(m);
            edge++;
            if (find(n) == find(m)) ok = 0;
            else merge(n, m);
        }
        else {
            if ((edge != 0 && edge != s.size() - 1) || !ok) {
                cout << "Case " << ++kase << " is not a tree." << endl;
            }
            else {
                cout << "Case " << ++kase << " is a tree." << endl;
            }
            edge = 0;
            ok = 1;
            s.clear();
            for (int i = 1; i < maxn; i++) fa[i] = i;
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/streamazure/p/13450065.html