您的位置:首页 > 其它

小学期训练题B-并查集

2015-07-25 09:15 351 查看
假期训练正式开始了, 然而我还是在补题。。。。

A:点击打开链接

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 30000 + 5;

int par[maxn];
int rank_[maxn];
int under[maxn];

void init()
{
    for(int i = 0; i < maxn; ++i)
    {
        par[i] = i;
        rank_[i] = 1;
        under[i] = 0;
    }
}
int find_(int x)
{
    if(par[x] == x) return x;
    int temp = par[x];
    par[x] = find_(par[x]);
    under[x] += under[temp];
    return par[x];
}
void unite(int x, int y)
{
    x = find_(x);
    y = find_(y);
    if(x == y) return;
    else
    {
        par[x] = y;
        under[x] = rank_[y];
        rank_[y] += rank_[x];
    }
}
int main()
{
    int N;
    while(cin >> N)
    {
        getchar();
        init();
        while(N--)
        {

            char s[3];
            scanf("%s", s);
            if(s[0] == 'M')
            {
                int x, y;
                scanf("%d%d", &x, &y);
                unite(x, y);
            }
            else if(s[0] == 'C')
            {
                int x;
                scanf("%d", &x);
                find_(x);
                printf("%d\n", under[x]);
            }
        }
    }
    return 0;
}
B:点击打开链接

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 5;
int par[maxn];
int rank_[maxn];
int kk[11][4] = { {1,1,0,0} , {0,1,1,0} , {1,0,0,1} , {0,0,1,1} , {0,1,0,1} ,
                 {1,0,1,0} , {1,1,1,0} , {1,1,0,1} , {1,0,1,1} , {0,1,1,1} , {1,1,1,1} };
void init()
{
    for(int i = 0; i < maxn; ++i)
    {
        par[i] = i;
        rank_[i] = 0;
    }
}
int find_(int x)
{
    if(par[x] == x)
        return x;
    else
        return par[x] = find_(par[x]);
}
void unite(int x, int y)
{
    x = find_(x);
    y = find_(y);
    if(x == y) return;
    if(rank_[x] < rank_[y])
        par[x] = y;
    else
    {
        par[y] = x;
        if(rank_[x] == rank_[y]) rank_[x]++;
    }
}
int main()
{
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF)
    {
        if(n==-1 && m==-1) break;
        init();
        char vis[50 + 5][50 + 5];
        for(int i = 0; i < n; ++i)
            scanf("%s", vis[i]);
        for(int i = 0; i < n; ++i)
        {
            for(int j = 0; j < m; ++j)
            {
                if(j>0 && kk[vis[i][j] - 'A'][0] == 1 && kk[vis[i][j-1] - 'A'][2] == 1)
                    unite(i*m+j, i*m + j-1);
                if(i>0 && kk[vis[i][j] - 'A'][1] == 1 && kk[vis[i-1][j] - 'A'][3] == 1)
                    unite(i*m+j, (i-1)*m + j);
            }
        }
        int cnt = 0;
        for(int i = 0; i < n*m; ++i)
        {
            if(par[i] == i) ++cnt;
        }
        cout << cnt << endl;
    }
}
C:点击打开链接

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1000 + 5;
int par[maxn];
int rank_[maxn];
void init()
{
    for(int i = 0; i < maxn; ++i)
    {
        par[i] = i;
        rank_[i] = 0;
    }
}
int find_(int x)
{
    if(par[x] == x)
        return x;
    else
        return par[x] = find_(par[x]);
}
void unite(int x, int y)
{
    x = find_(x);
    y = find_(y);
    if(x == y) return;
    if(rank_[x] < rank_[y])
        par[x] = y;
    else
    {
        par[y] = x;
        if(rank_[x] == rank_[y]) rank_[x]++;
    }
}
int main()
{
    int N, M;
    while(cin >> N && N)
    {
        cin >> M;
        init();
        for(int i = 0; i < M; ++i)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            unite(x, y);
        }
        int cnt = 0;
        for(int i = 1; i <= N; ++i)
        {
            if(find_(i) == i)
                ++cnt;
        }
        cout << cnt - 1 << endl;
    }
}
D:点击打开链接

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 100000;
bool ans[maxn];
int _rank[maxn];
int _par[maxn];
void INIT()
{
    for(int i = 1; i < maxn; ++i) _rank[i] = 0;
    for(int i = 1; i < maxn; ++i) _par[i] = i;
}
int _Find(int x)
{
    return _par[x] == x ? _par[x] : _par[x] =  _Find(_par[x]);
}
void Unite(int x, int y)
{
    x = _Find(x); y = _Find(y);
    if(x==y) return ;
    if(_rank[x] < _rank[y]) _par[x] = y;
    else
    {
        _par[y] = x;
        if(_rank[x] == _rank[y]) _rank[x]++;
    }
}
int main()
{
    int x,y;
    while(scanf("%d%d", &x, &y) == 2)
    {
        if(x==0&&y==0) cout << "Yes" << endl;
        if(x==-1 && y==-1) break;
        INIT();
        ans[x] = ans[y] = 1;
        Unite(x,y);
        bool ok = true;
        while(scanf("%d%d", &x, &y) == 2)
        {
            if(x==0 && y==0) break;
            ans[x] = ans[y] = 1;
            x = _Find(x); y = _Find(y);
            Unite(x,y);
            if(x==y) ok = false;
        }
        int cnt = 0;
        for(int i = 1; i < maxn; ++i)
        {
            if(ans[i] && _par[i] == i) ++cnt;
            if(cnt>1) {ok = false; break;}
        }
        if(ok) cout << "Yes" << endl;
        else  cout << "No" << endl;
        memset(ans,0,sizeof(ans));
    }
    return 0;
}
E:点击打开链接

#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
int par[maxn];
int vis[maxn];
int main()
{
    int x,y;
    int kase = 0;
    while(1)
    {
        int sum = 0;
        int cnt = 0;
        bool ok = true;
        memset(par,0,sizeof(par));
        memset(vis,0,sizeof(vis));
        int n = 0;
        for(n = 0; ; ++n)
        {
            scanf("%d%d", &x, &y);
            if(x < 0 && y < 0) return 0;
            if(x==0 && y==0) break;
            if(!vis[x]) ++cnt, ++sum, vis[x] = 1;
            if(!vis[y]) ++sum, vis[y] = 1;
            else --cnt;
            if(par[y] != 0) ok = false;
            par[y] = x;
        }
        if(n != 0 && n != sum-1) ok = false;
        if(n != 0 && cnt != 1) ok = false;
        if(ok) printf("Case %d is a tree.\n", ++kase);
        else printf("Case %d is not a tree.\n", ++kase);
    }
    return 0;
}
F:点击打开链接

#include<iostream>
#include<cstdio>
#include<set>
#include<string.h>
#include<algorithm>
using namespace std;

const int maxn = 2000000 + 5;

int par[maxn];
int kk[maxn];

void init()
{
    for(int i = 0; i < maxn; ++i)
    {
        par[i] = i;
        kk[i] = i;
    }
}
int find_(int x)
{
    if(par[x] == x)
        return x;
    else
        return par[x] = find_(par[x]);
}
void unite(int x, int y)
{
    x = find_(x);
    y = find_(y);
    if(x != y)
        par[x] = y;
}
int main()
{
    int n, m;
    int kase = 0;
    while (cin >> n >> m)
    {
        if(n==0 && m==0) return 0;
        init();
        int cnt = n;
        while(m--)
        {
            char s[3];
            scanf("%s", s);
            if (s[0] == 'M')
            {
                int x, y;
                scanf("%d%d", &x, &y);
                unite(kk[x], kk[y]);
            }
            else if(s[0] == 'S')
            {
                int x;
                scanf("%d", &x);
                kk[x] = cnt;
                par[cnt] = cnt;
                ++cnt;
            }
        }
        set <int> vis;
        for (int i = 0; i < n; i++)
            vis.insert(find_(kk[i]));
        printf("Case #%d: %d\n", ++kase, vis.size());
    }
    return 0;
}


并查集本身没有啥难的, 主要是它的变形应用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: