hdu 1232, disjoint set, linked list vs. rooted tree, a minor but substantial optimization for path c
来源:互联网 发布:什么是淘宝客服工作 编辑:程序博客网 时间:2024/05/21 18:33
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 1005struct 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\n",cnt); } return 0;}
// rooted tree version, with rank by union and path compression, 31 ms
#include <cstdio>#include <cstring>#include <algorithm>#define MAXSIZE 1005struct 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\n",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 1005struct 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\n",cnt); } return 0;}
- hdu 1232, disjoint set, linked list vs. rooted tree, a minor but substantial optimization for path c
- Path Sum and Delete Node in a Linked List
- C++: delete a node from linked list
- HDU 1232 畅通工程(并查集Disjoint Set 经典)
- Leetcode优化:Convert a binary tree to linked list
- "same tree" and "Delete Node in a Linked List"
- Convert a Binary Tree to Doubly Linked List
- P27 (**) Group the elements of a set into disjoint subsets.
- 【C++】【LeetCode】114. Flatten Binary Tree to Linked List
- 编程算法 - 并查集(disjoint set) 代码(C)
- Python list vs set
- reverse a linked list
- Reverse a linked list.
- Reverse a linked list
- Reverse A Linked List
- reverse a linked list
- Reverse a linked list
- reverse a linked list
- iOS如何实现国际化(本地化)
- 算法的封装与切换——策略模式(三)
- Java构造和解析Json数据的两种方法详解二
- HttpClient上传文件到微信素材乱码问题解决
- SQL分组后内部排序
- hdu 1232, disjoint set, linked list vs. rooted tree, a minor but substantial optimization for path c
- MFC学习之路01 快捷键的生成方法
- 生成sqlite3.lib for bcb/vc
- 算法导论 第十三章:红黑树
- 字典树的应用 单词意义查找-C语言实现
- hadoop中最简单最简单的map-reduce
- 前台jsp控件获取java后台返回的值
- NYOJ 362 解题报告
- 循环语句的小程序