hdu1232畅通工程 并查集

时间:2023-02-11 09:54:18

题目链接

并查集入门题。

数组结构code1:

#include<iostream>
#define maxn 1005
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
using namespace std;
int set[maxn];
int ifhas[maxn];
int s,e;
int n,m;
void init()
{
    int i,j;
    for(i = 1;i <= n;i ++){
        set[i] = i;
        ifhas[i] = 0;
    }
}
void Merge(int a,int b)
{
    int big,small;
    big = max(set[a],set[b]);
    small= min(set[a],set[b]);
    for(int i = 1;i <= n;i ++)
    {
        if(set[i] == big){
            set[i] = small;
        }
    }
}
int main(void)
{
    while(cin >> n && n!=0)
    {
        init();
        cin >> m;
        int i,j;
        for(i = 0;i < m;i ++){
            cin >> s >> e;
            Merge(s,e);
        }
        int ans = 0;
        for(int i = 1;i <= n;i ++)
        {
            if(ifhas[set[i]] == 0){
                ans ++;
                ifhas[set[i]] = 1;
            }
        }
        cout << ans - 1 << endl;
    }
    return 0;
}

 树结构code2

#include <iostream>
#include <algorithm>
#define maxn 1005
using namespace std;
int set[maxn];void init(int n)
{
    int i;
    for(i = 1;i <=n;i ++)
    {
        set[i] = i;
    }
}
int find(int x)
{
    int fa = x;
    while(fa != set[fa])
        fa = set[fa];
    return fa;
}
void merge(int a,int b)
{
    int fa,fb;
    fa = find(a);
    fb = find(b);
    set[fb] = fa;
}
int main()
{
    int n,m,a,b;
    
    while(cin >> n && n!= 0)
    {
        init(n);
        cin >> m;
        for(int i = 1;i <= m;i ++){
            cin >> a >> b;
            merge(a,b);
        }
        for(int i = 1;i <= n;i ++){
            set[i] = find(i);
            //cout << "set[" << i << "]=" << set[i] << endl;
        }
        int ans = 0;
        for(int i = 1;i <= n;i ++)
        {
            if(set[i] == i){
                ans ++;
            }
        }
        cout << ans - 1 << endl;
    }
    return 0;
}

树结构(优化,深度小的移到深度大的)

#include <iostream>
#include <algorithm>
#define maxn 1005
using namespace std;
int set[maxn];
int height[maxn];
void init(int n)
{
    int i;
    for(i = 1;i <=n;i ++)
    {
        set[i] = i;
        height[i] = 1;
    }
}
int find(int x)
{
    int fa = x;
    while(fa != set[fa])
        fa = set[fa];
    return fa;
}
void merge(int a,int b)
{
    int fa,fb;
    fa = find(a);
    fb = find(b);
    if(height[fa] > height[fb]){
        set[fb] = fa;
    }
    else if(height[fb] > height[fa]){
        set[fa] = fb;
    }
    else{
        set[fb] = fa;
        height[fa] ++;
    }
}
int main()
{
    int n,m,a,b;
    
    while(cin >> n && n!= 0)
    {
        init(n);
        cin >> m;
        for(int i = 1;i <= m;i ++){
            cin >> a >> b;
            merge(a,b);
        }
        for(int i = 1;i <= n;i ++){
            set[i] = find(i);
            //cout << "set[" << i << "]=" << set[i] << endl;
        }
        int ans = 0;
        for(int i = 1;i <= n;i ++)
        {
            if(set[i] == i){
                ans ++;
            }
        }
        cout << ans - 1 << endl;
    }
    return 0;
}

树结构(优化,深度小的移到深度大的 + 路径压缩)

#include <iostream>
#include <algorithm>
#define maxn 1005
using namespace std;
int set[maxn];
int height[maxn];
void init(int n)
{
    int i;
    for(i = 1;i <=n;i ++)
    {
        set[i] = i;
        height[i] = 1;
    }
}
int find(int x)
{
    int fa = x;
    int j,i;
    while(fa != set[fa])
        fa = set[fa];
    i = x;
    while(i != fa)
    {
        j = set[i];
        set[j] = fa;
        i = j;
    }
    return fa;
}
void merge(int a,int b)
{
    int fa,fb;
    fa = find(a);
    fb = find(b);
    if(height[fa] > height[fb]){
        set[fb] = fa;
    }
    else if(height[fb] > height[fa]){
        set[fa] = fb;
    }
    else{
        set[fb] = fa;
        height[fa] ++;
    }
}
int main()
{
    int n,m,a,b;
    
    while(cin >> n && n!= 0)
    {
        init(n);
        cin >> m;
        for(int i = 1;i <= m;i ++){
            cin >> a >> b;
            merge(a,b);
        }
        for(int i = 1;i <= n;i ++){
            set[i] = find(i);
            //cout << "set[" << i << "]=" << set[i] << endl;
        }
        int ans = 0;
        for(int i = 1;i <= n;i ++)
        {
            if(set[i] == i){
                ans ++;
            }
        }
        cout << ans - 1 << endl;
    }
    return 0;
}