zoukankan      html  css  js  c++  java
  • hdu 1232, disjoint set, linked list vs. rooted tree, a minor but substantial optimization for path c 分类: hdoj 2015-07-16 17:13 116人阅读 评论(0) 收藏

    three version are provided.
    disjoint set, linked list version with weighted-union heuristic, rooted tree version with rank by union and path compression, and a minor but substantial optimization for path compression version FindSet to avoid redundancy so to be more efficient. (31 ms to 15 ms)
    reference:
    1. Thomas H. Cormen, Introduction to Algorithms
    2. Disjoint-set Data Structures By vlad_D– TopCoder Member https://www.topcoder.com/community/data-science/data-science-tutorials/disjoint-set-data-structures/
    in linked list version with weighted-union heuristic, with a extra tail member in struct myNode to speedup union, find is O(1), simply the p->head, so I remove find() and just used p->head as the find function.
    (one main point) every time a list become no longer list, change its head’s num from 1 to 0, thus facilitate the afterwards count process – all node’s num is simply 0 except the ones as the head of linked lists. – similar process in the rooted tree version.

    // linked list version with weighted-union heuristic, 15 ms

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    #define MAXSIZE 1005
    struct myNode {
        int num;
        myNode *head;
        myNode *next;
        myNode *tail;
    };
    
    void MergeSet(myNode *p1, myNode *p2) {
        p1=p1->head, p2=p2->head;
        if(p1->num<p2->num) { std::swap(p1,p2); }
        p1->num+=p2->num, p2->num=0;
        p1->tail->next=p2, p1->tail=p2->tail;
        for(;p2;p2=p2->next) { p2->head=p1; }
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
        int T, n,m,u,v,i,cnt;
        myNode cities[MAXSIZE], *p,*pend, *q;
        while(scanf("%d%d",&n,&m)==2 && n>0) {
            for(p=&cities[1],pend=p+n;p!=pend;++p) { p->num=1; p->head=p; p->next=0; p->tail=p; }
            for(i=0;i<m;++i) {
                scanf("%d%d",&u,&v);
                if(cities[u].head!=cities[v].head) { MergeSet(&cities[u],&cities[v]); }
            }
            for(cnt=-1, p=&cities[1],pend=p+n;p!=pend;++p) {
                if(p->num>0) ++cnt;
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }

    // rooted tree version, with rank by union and path compression, 31 ms

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    #define MAXSIZE 1005
    struct myNode {
        int rank;
        myNode *parent;
    };
    
    myNode* FindSet(myNode *p1) {
        if(p1->parent==p1) return p1;
        return p1->parent=FindSet(p1->parent);
    }
    
    void Link(myNode *p1, myNode *p2) {
        if(p1->rank<p2->rank) std::swap(p1,p2);
        p2->parent=p1;
        p2->rank=0;
        if(p1->rank==p2->rank) ++p1->rank;
    }
    
    void MergeSet(myNode *p1, myNode *p2) {
        Link(FindSet(p1),FindSet(p2));
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
        int T, n,m,u,v,i,cnt;
        myNode cities[MAXSIZE], *p,*pend, *q;
        while(scanf("%d%d",&n,&m)==2 && n>0) {
            for(p=&cities[1],pend=p+n;p!=pend;++p) { p->rank=1; p->parent=p; }
            for(i=0;i<m;++i) {
                scanf("%d%d",&u,&v);
                if(FindSet(&cities[u])!=FindSet(&cities[v]))
                    MergeSet(&cities[u],&cities[v]);
            }
            for(cnt=-1, p=&cities[1],pend=p+n;p!=pend;++p) {
                if(p->rank>0) ++cnt;
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }

    note that in version 2, the path compression FindSet is a two pass recursive function, first pass up to find parent and then pass down return it to update p->parent, thus achieve path compression.
    (another main point) But, note that, even when p->parent is the representative, there is no need to update p->parent, FindSet still obliviously call FindSet(p->parent) and assign it to p->parent, which does nothing useful. We can remove this redundancy by a simple modification, in FindSet, replace

    if(p1->parent==p1) return p1;

    with

    if(p1->parent==p1->parent->parent) return p1->parent;

    // almost same with version 2, with the optimization just mentioned, 15 ms

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    #define MAXSIZE 1005
    struct myNode {
        int rank;
        myNode *parent;
    };
    
    myNode* FindSet(myNode *p1) {
        if(p1->parent==p1->parent->parent) return p1->parent;
        return p1->parent=FindSet(p1->parent);
    }
    
    void Link(myNode *p1, myNode *p2) {
        if(p1->rank<p2->rank) std::swap(p1,p2);
        p2->parent=p1;
        p2->rank=0;
        if(p1->rank==p2->rank) ++p1->rank;
    }
    
    void MergeSet(myNode *p1, myNode *p2) {
        Link(FindSet(p1),FindSet(p2));
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
        int T, n,m,u,v,i,cnt;
        myNode cities[MAXSIZE], *p,*pend, *q;
        while(scanf("%d%d",&n,&m)==2 && n>0) {
            for(p=&cities[1],pend=p+n;p!=pend;++p) { p->rank=1; p->parent=p; }
            for(i=0;i<m;++i) {
                scanf("%d%d",&u,&v);
                if(FindSet(&cities[u])!=FindSet(&cities[v]))
                    MergeSet(&cities[u],&cities[v]);
            }
            for(cnt=-1, p=&cities[1],pend=p+n;p!=pend;++p) {
                if(p->rank>0) ++cnt;
            }
            printf("%d
    ",cnt);
        }
        return 0;
    }

    版权声明:本文为博主原创文章,未经博主允许不得转载。// p.s. If in any way improment can be achieved, better performance or whatever, it will be well-appreciated to let me know, thanks in advance.

  • 相关阅读:
    【Azure 应用服务】在Azure App Service多实例的情况下,如何在应用中通过代码获取到实例名(Instance ID)呢?
    【Azure 应用服务】App Service For Windows 中如何设置代理实现前端静态文件和后端Java Spring Boot Jar包
    【Azure Developer】使用Azure Key Vault 的Key签名后,离线验证的一些参考资料
    【Azure Function】调试 VS Code Javascript Function本地不能运行,报错 Value cannot be null. (Parameter 'provider')问题
    【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(Xms512m Xmx1204m)?
    【Azure API 管理】APIM添加Logtoeventhub的策略后,一些相关APIM与Event Hub的问题
    【Azure API 管理】为调用APIM的请求启用Trace 调试APIM Policy的利器
    【Azure 事件中心】China Azure上是否有Kafka服务简答
    【Azure 应用服务】探索在Azure上设置禁止任何人访问App Service的默认域名(Default URL)
    【Azure 微服务】记一次错误的更新Service Fabric 证书而引发的集群崩溃而只能重建
  • 原文地址:https://www.cnblogs.com/qeatzy/p/4716216.html
Copyright © 2011-2022 走看看