POJ2524(Ubiquitous Religions)--并查集
题目链接:http://poj.org/problem?id=2524
学校有n个学生,但是你不能直接问学生的信仰,不然他会感到很不舒服的.一个方法是问m对同学,是否信仰同一宗教。根据这些数据,
计算学校最多有多少种宗教信仰的。
思路:使用并查集,一开始假设大家都各自信仰一个宗教,那么总的数目ans就是学生数目,
当发现有一对学生信仰同一个宗教,那么ans减1。
1 #include<iostream> 2 #include<stdio.h> 3 #include<cstring> 4 #include<cmath> 5 #include<vector> 6 #include<stack> 7 #include<map> 8 #include<set> 9 #include<list> 10 #include<queue> 11 #include<string> 12 #include<algorithm> 13 #include<iomanip> 14 using namespace std; 15 16 17 struct node 18 { 19 /* data */ 20 int date;//结点对应的下标 21 int parent;//双亲结点 22 int rank;//结点对应秩(并查集树的深度) 23 int relation; //与父节点的关系 24 int total; 25 }; 26 27 class DisJoinSet 28 { 29 protected: 30 int n;//元素个数 31 node *tree;//并查集元素数组 32 public: 33 int ans; 34 DisJoinSet(int n ); 35 ~DisJoinSet(); 36 void Init(); 37 int Find(int x);// 查找x的代表元素(根),查找的同时进行路径压缩 38 void Union(int x,int y); 39 int GetAnswer();// 合并x和y 40 }; 41 42 DisJoinSet::DisJoinSet(int n) 43 { 44 this->n = n ; 45 tree = new node [n+1]; 46 Init(); 47 ans = n; 48 } 49 50 void DisJoinSet ::Init() 51 { 52 for(int i = 1 ;i <=n; i++)//顶点编号 0~n-1 或 1 ~ n都 行 53 { 54 tree[i].parent = i;//双亲初始化指向自已 55 tree[i].rank = 0;//秩初始化为0 56 tree[i].date = i;//编号 57 tree[i].relation = 0; //i自己是一类,它的父节点此时就是它自己,属于同一类 58 } 59 } 60 61 DisJoinSet::~DisJoinSet() 62 { 63 delete []tree; 64 } 65 66 int DisJoinSet::Find(int x)//查找x的代表元素(根),查找的同时进行路径压缩 67 { 68 int temp = tree[x].parent;// 将x父节点的下标存入temp 69 if( x != tree[x].parent)//若双亲不是自已 70 { 71 tree[x].parent = Find(tree[x].parent);//递归在双亲中找x 72 return tree[x].parent;// 返回根节点下标 73 } 74 return x;//若双亲是自已,返回x 75 } 76 77 void DisJoinSet::Union(int x,int y) 78 { 79 int rootx = Find(x);// 找到下标为x的元素的根节点下标rootx 80 int rooty = Find(y);// 找到下标为y的元素的根节点下标rooty 81 if(rootx == rooty)// 已合并,直接返回 82 { 83 return ; 84 } 85 else 86 { 87 if(tree[rootx].rank > tree[rooty].rank)//rooty结点的秩(深度)小于rootx结点的秩 88 { 89 tree[rooty].parent = rootx;//将rooty连到rootx结点上,rootx作为rooty的孩子结点 90 ans--;//合并两个人,总人数-1 91 tree[rootx].total +=tree[rooty].total; 92 } 93 else 94 { 95 tree[rootx].parent = rooty; 96 ans--;//合并两个人,总人数-1 97 tree[rooty].total += tree[rootx].total; 98 if(tree[rootx].rank == tree[rooty].rank) 99 { 100 tree[rooty].rank++; 101 } 102 } 103 } 104 } 105 106 int main() 107 { 108 int n; 109 int m; 110 int t = 1; 111 while(cin>>n>>m && n !=0 &&m != 0) 112 { 113 DisJoinSet dis(n); 114 int a,b; 115 for(int i = 1 ;i <= m; i++) 116 { 117 cin>>a>>b; 118 dis.Union(a,b); 119 } 120 cout<<"Case "<<t++<<": "<<dis.ans<<endl; 121 } 122 return 0; 123 }
----------------------------------------------------------------------------------------------------------------转载请说明出处----------------------------------------------------------------------------------------------------------------------
你要做一个不动声色的大人了。不准情绪化,不准偷偷想念,不准回头看。去过自己另外的生活。你要听话,不是所有的鱼都会生活在同一片海里。
————————村上春树