HDU 1272 小希的迷宫 【并查集好题】

传送门
// 题意: 问给定的一幅图是否任意两点之间有且仅有一条路径.

思路: 首先一种比较笨的方法就是先并查集维护联通性, 然后用dfs判断图是否有环, 比较麻烦, 但是也能过., 当然最好的方法就是用并查集也可以判环, 当然你的并查集是用了启发式合并的, 所以我们就有每个点的所在集合的size, 图中有环是什么情况了, 也就是某个点的size或翻一倍, 也就是最终的点的size不可能刚好等于总点数, 所以扫一遍判断一下就OK啦…
这是因为我们连接的两个点并没有去管他们是否是在同一个集合中, 但是题目是不允许的, 所以我们可以根据这个点来判断是否符合题意!…..

AC Code

const int maxn = 1e5 + 5;
int fa[maxn], r[maxn];
int a[maxn], vis[maxn];
void init(int n) {
   for(int i = 1 ; i<= n ; i++){
      fa[i] = i;
      r[i] = 1;
   }
   Fill(vis, 0);
}
int Find(int x) {
   return fa[x] == x ? x : fa[x] = Find(fa[x]);
}
void Un(int x, int y) {
   x = Find(x), y = Find(y);
   if(r[x] < r[y])
      swap(x, y);
   fa[y] = x;
   r[x] += r[y];
}
void solve()
{
    int u, v;
    while(scanf("%d%d", &u, &v)) {
        init(maxn-5);
        if (!u && !v) {
            printf("Yes\n");
            continue;
        }
        if (u == -1 && v == -1) break;
        int sum = 0, k = 0;
        if (!vis[u]) sum++, a[++k] = u;
        if (!vis[v]) sum++, a[++k] = v;
        vis[u] = vis[v] = 1;
        u = Find(u); v = Find(v);
        Un(u, v);
        while(~scanf("%d%d", &u, &v)) {
            if (u + v == 0) break;
            if (!vis[u]) sum++, a[++k] = u;
            if (!vis[v]) sum++, a[++k] = v;
            vis[u] = vis[v] = 1;
            u = Find(u); v = Find(v);
            Un(u, v);
        }
        int flag = 0;
        for (int i = 1 ; i <= k ; i ++) {
             if (r[a[i]] == sum) {
                flag = 1;
                break;
             }
        }
        if (!flag) printf("No\n");
        else printf("Yes\n");
    }
}

你可能感兴趣的:((带权)并查集)