zoukankan      html  css  js  c++  java
  • 用父亲结点数组实现并查集

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<algorithm>
     4 using namespace std;
     5 typedef struct ufset *UFset;
     6 struct ufset
     7 {
     8     int parent[100001];
     9     int root[100001];
    10 }UFS;
    11 int s[100001],y[100001],d[10000],add;
    12 int UFfind(int e,UFset U)
    13 {
    14     int i,j=e;
    15     while(U->root[j]==0)
    16     {
    17         j=U->parent[j];
    18     }
    19     while(j!=e)
    20     {
    21         i=U->parent[e];
    22         U->parent[e]=j;
    23         e=i;
    24     }
    25     return j;
    26 }
    27 int UFunion(int i,int j,UFset U)
    28 {
    29         U->parent[j]+=U->parent[i];
    30         U->root[i]=0;
    31         U->parent[i]=j;
    32         return j;
    33 }
    34 int main()
    35 {
    36     UFset UF;
    37     UF=(UFset)malloc(sizeof(UFS));
    38     int e,n,m,k,x,i,a,b,t1,t2;
    39     scanf("%d %d",&n,&m);
    40     for(e=1;e<=n+1;e++)
    41     {
    42         UF->parent[e]=1;
    43         UF->root[e]=1;
    44     }
    45     for(i=0;i<m;i++)
    46     {
    47         scanf("%d %d",&a,&b);
    48         t1=UFfind(a,UF);t2=UFfind(b,UF);
    49         if(t1!=t2)
    50         {
    51             UFunion(t1,t2,UF);
    52         }
    53     }
    54     int t=0; 
    55     for(i=1;i<n+1;i++)
    56     {
    57         if(UF->root[i]==1)
    58         {
    59             s[t]=UF->parent[i];
    60             y[t++]=i;
    61         }        
    62     }
    63     sort(s,s+t);
    64     add=k=0;
    65     for(i=1;;i++)
    66     {
    67         if(add>=n)
    68             break;
    69         else
    70         {
    71             add+=s[t-i];
    72             d[k++]=UFfind(y[t-i],UF);
    73         }
    74     }
    75     printf("%d
    ",k);
    76     sort(d,d+k);
    77     for(i=0;i<k;i++)
    78     {
    79         if(i<k-1)
    80         printf("%d ",d[i]);
    81         else
    82             printf("%d
    ",d[i]);
    83     }
    84     return 0;
    85 }
    View Code

     并查集结构简单。在数据结构作业大招秒杀和战争来了中有巧妙的运用

    在下面所描述的改进的并查集结构中增加一个根节点数组root,用来记录树的根结点。
    当元素e所在结点不是根节点时,root[e]=0,parent[e]=表示其父节点;当元素e所在结点是根节点
    时,root[e]=1,parent[e]的值是树中结点的个数.

    1 typedef struct ufset *UFset;
    2 struct ufset
    3 {
    4     int parent[100];
    5     int root[100];
    6 }UFS;

    UFfind(e.U)运算从元素e相应的结点走到树根处,找出所在集合的元素
    加速并查集运算的另一的办法就是采用路径压缩技术,在执行UFfind时,实际是找到了从一个结点
    到树根的一条路径。路径压缩技术就是把这条路上的所有结点都改为树根的儿子,实现路径压缩的最简单方法是
    在这条路上走两次,第一次找到树根,第二次将路上所有结点的父节点都改为树根。

    int UFfind(int e,UFset U)
    {
        int i,j=e;
        while(U->root[j]==0)
        {
            j=U->parent[j];
        }
        while(j!=e)
        {
            i=U->parent[e];
            U->parent[e]=j;
            e=i;
        }
        return j;
    }

    在最坏情况下,合并可能使n个结点的数退化成一条链,在这种情下,对所有元素各执行
    一次UFfind将耗时O(N*N) 。所以,尽管,UFunion只需要O(1)时间,当UFfind可能是总时间
    耗费很大,为了克服这个缺点。可以做以下改进,使得每次UFind不超过O(longn)时间。在树
    根中保存该树的结点数,每次合并时,总将小树合并到大树上。当一个结点从一棵树移到另
    一颗数上时,这个节点到树根的距离就增加1,而这个节点所在的树的大小至少增加一倍。
    于是并查集中每一个结点至多被移动O(longn)次,从而每个节点到树根的距离不会超过O(longn)。
    所以每次UFfind运算只需要O(longn)时间。

    int UFunion(int i,int j,UFset U)
    {
        if(U->parent[i]<U->parent[j])
        {
            U->parent[j]+=U->parent[i];
            U->root[i]=0;
            U->parent[i]=j;
            return j;
        }
        else
        {
            U->parent[j]+=U->parent[i];
            U->root[j]=0;
            U->parent[j]=i;
            return i;
        }
    }
  • 相关阅读:
    pandas 和反射联合使用
    反射
    获取Cookie 遇到的问题
    接口自动化之 问题
    接口自动化之 数据库操作
    logging日志模块
    数据驱动 --ddt
    logging--日志打印模块
    APP专项测试5 --PFS
    Monkey 参数
  • 原文地址:https://www.cnblogs.com/zeze/p/UFS1.html
Copyright © 2011-2022 走看看