zoukankan      html  css  js  c++  java
  • 并查集专题

    2019.7.15

    并查集专题

    HDU 1213

    并查集裸题,把一些点连起来,问有多少个pre[i] = i;

    #include <cstdio>
    #include <cstring>
    
    int pre[1010];
    int findn(int son) {
        int root = son;
        while(son != pre[son]) son = pre[son];
        while(root != son) {
            int t = pre[root];
            pre[root] = son;
            root = t;
        }
        return son;
    }
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            int n, m, a, b;
            scanf("%d %d", &n, &m);
            for(int i = 1; i <= n; i++) pre[i] = i;
            while(m--) {
                scanf("%d %d", &a, &b);
                a = findn(a);
                b = findn(b);
                if(a != b) {
                    pre[a] = b;
                    n--;
                }
            }
            printf("%d
    ", n);
        }
        return 0;
    }
    

    POJ 2236

    给出一些电脑的坐标,如果电脑被修好了,那么和他距离d以内的被修好的电脑就能和他相连,如果a和b相连,b和c相连,那么a和c也相连,询问两台电脑是否相连

    注意输出SUCCESS,FAIL

    #include <cstdio>
    #include <cstring>
    
    struct node
    {
        int x, y;
    }a[1010];
    int pre[1010];
    
    int findn(int son) {
        int root = son;
        while(son != pre[son]) son = pre[son];
        while(root != son) {
            int t = pre[root];
            pre[root] = son;
            root = t;
        }
        return son;
    }
    bool flag[1010];
    int main() {
        memset(flag, false, sizeof(flag));
        int n, d, b, c;
        char s[2];
        scanf("%d %d", &n, &d);
        for(int i = 1; i <= n; i++) {
            scanf("%d %d", &a[i].x, &a[i].y);
            pre[i] = i;
        }
        while(~scanf("%s", s)) {
            if(s[0] == 'S') {
                scanf("%d %d", &b, &c);
                if(findn(b) == findn(c)) printf("SUCCESS
    ");
                else printf("FAIL
    ");
            }
            else {
                scanf("%d", &b);
                if(flag[b] == false) {
                    flag[b] = true;
                    for(int i = 1; i <= n; i++) {
                        if(flag[i] == true && (a[i].x - a[b].x)*(a[i].x - a[b].x) + (a[i].y - a[b].y) * (a[i].y - a[b].y) <= d*d) {
                            int root1 = findn(b);
                            int root2 = findn(i);
                            if(root1 != root2) pre[root1] = root2;
                        }
                    }
                }
            }
        }
        return 0;
    }
    

    HDU 3038

    给出多个区间的和,区间的元素可以是负数,如果输入的区间和不合理就lies++;

    最后输出lies;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=200050;
    int n,m;
    int fa[N],rankk[N];
    int findd(int x)
    {
        if(x==fa[x])return x;
        int temp=fa[x];
        fa[x]=findd(fa[x]);
        rankk[x]+=rankk[temp];
        return fa[x];
    }
    bool unite(int x,int y,int c)
    {
        int xx=findd(x),yy=findd(y);
        if(xx==yy)
        {
            if(rankk[y]!=rankk[x]+c) return false;
            return true;
        }
        fa[yy]=xx;
        rankk[yy]=rankk[x]-rankk[y]+c;
        return true;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            int lies = 0;
            for(int i=0;i<=n;i++) {
                fa[i]=i;
                rankk[i]=0;
            }
            while(m--)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                if(a>b) swap(a,b);
                if(!unite(a-1,b,c)) lies++;
            }
            printf("%d
    ",lies);
        }
        return 0;
    }
    

    ZOJ 3261

    有n个星球,这些星球都有一个能力值,只有能力值小的可以向能力值大的星球求助,这些星球本来有是相连的,下面可以进行两种操作,第一种是查询该星球可以向哪个星球求助,第二种是破坏某两个星球的路。

    #include<cstdio>
    #include<cstring>
    #include<map>
    using std:: map;
    const int maxn = 10010;
    const int maxm = 20010;
    const int maxk = 50010;
    int par[maxn], pow[maxn];
    map<int, int>mp[maxn];
    bool vis[maxm];
    struct node
    {
        int bol, a, b;
    };
    node ope[maxk];
    struct nodee
    {
        int a, b;
    };
    nodee side[maxm];
    int fid(int x) {
        int son, temp;
        son = x;
        while(x != par[x]) x = par[x];
        while(son != x) {
            temp = par[son];
            par[son] = x;
            son = temp;
        }
        return x;
    }
    void swap(int *a, int *b) {
        int c;
        c = *a;
        *a = *b;
        *b = c;
    }
    void con(int x, int y) {
        int fx = fid(x);
        int fy = fid(y);
        if(pow[fx] > pow[fy]) par[fy] = fx;
        else if(pow[fx] == pow[fy])
        {
            if(fx<=fy) par[fy] = fx;
            else par[fx] = fy;
        }
        else par[fx] = fy;
    }
    int main()
    {
        int n, m, k, a, b, flag = 0;
        char s[50];
        while(~scanf("%d", &n)) {
            if(flag) printf("
    ");
            else flag = 1;
            memset(vis, false, sizeof(vis));
            for(int i = 0; i < n; i++) {
                scanf("%d", &pow[i]);
                par[i] = i;
                mp[i].clear();
            }
            scanf("%d", &m);
            for(int i = 0; i < m; i++) {
                scanf("%d %d", &a, &b);
                if(a > b) swap(&a, &b);
                side[i].a = a;
                side[i].b = b;
                mp[a][b] = i;
                vis[i] = true;
            }
            scanf("%d", &k);
            for(int i = 0;  i < k; i++) {
                scanf("%s", s);
                if(s[0] == 'q') {
                    ope[i].bol = 1;
                    scanf("%d", &ope[i].a);
                }
                else {
                    ope[i].bol = 2;
                    scanf("%d %d", &a, &b);
                    if (a > b) swap(&a, &b);
                    ope[i].a = a;
                    ope[i].b = b;
                    vis[mp[a][b]] = false;
                }
            }
            for(int i = 0; i<m; i++) {
                if(vis[i]) {
                    con(side[i].a, side[i].b);
                }
            }
            int cnt = 0, ans[k];
            for(int i = k - 1; i >= 0; i--) {
                if(ope[i].bol == 1) {
                    int x=ope[i].a;
                    int f=fid(x);
                    if(pow[f] > pow[x]) ans[cnt++] = f;
                    else ans[cnt++] = -1;
                }
                else {
                    con(ope[i].a, ope[i].b);
                }
            }
            for(int i = cnt - 1; i >= 0; i--)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
    

    HDU 1272

    查询是否存在环且每个点是否能连通。

    #include <cstdio>
    int pre[100010];
    int findn(int son) {
        int root = son;
        while(son != pre[son]) son = pre[son];
        while(root != son) {
            int t = pre[root];
            pre[root] = son;
            root = t;
        }
        return son;
    }
    int main() {
        int a, b;
        while(1) {
            int flag = 0, vis[100010], cnt = 0;
            bool bol[100010];
            for(int i = 1; i < 100010; i++) pre[i] = i, bol[i] = false;
            while(1) {
                scanf("%d %d", &a, &b);
                if(a == 0 && b == 0 && cnt == 0) {
                    printf("Yes
    ");
                    continue;
                }
                if((a == 0 && b == 0) || (a == -1 && b == -1)) {
                    break;
                }
                if(bol[a] == false) vis[cnt++] = a;
                if(bol[b] == false) vis[cnt++] = b;
                bol[a] = bol[b] = true;
                if(flag == 0) {
                    a = findn(a);
                    b = findn(b);
                    if(a == b) {
                        flag = 1;
                    }
                    else pre[a] = b;
                }
            }
            int ans = 0;
            if(a == -1 && b == -1) break;
            else {
                if(flag) printf("No
    ");
                else {
                    for(int i=0; i<cnt; i++) {
                        if(pre[vis[i]] == vis[i]) ans++;
                    }
                    if(ans == 1) printf("Yes
    ");
                    else printf("No
    ");
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    nginx+ftp图片服务器搭建
    第一篇随笔
    字符设备控制技术
    总结字符设备
    字符设备驱动模型
    使用字符设备驱动
    驱动开发前奏
    linux内核链表的移植与使用
    linux内存管理子系统
    内核模块可选信息
  • 原文地址:https://www.cnblogs.com/fanshhh/p/11198381.html
Copyright © 2011-2022 走看看