并查集的基本运用 POJ1611

用并查集的情况是在比如 A和B联通  B和C联通那么 ABC联通 这类情况下算某个元素所在集合的元素个数。.

并查集数据结构用数组就行,数组的下标表示相应的一个主体,对应的值表示它的父节点的索引,指向父节点。根节点的值特殊一下就行;

原理:先把所有结点(元素)看成独立的集合,然后按给的条件来合并,合并的过程就是最重要的,结合已知条件,因为并查集是用于A和B联通  B和C联通那么 ABC联通 这类情况下算某个元素所在集合的元素个数   所以合并过程是把2个元素所在集合合并,实际情况就是比如已知AC合在一个集合了A为代表元素 后面跟着是DLK这个集合代表元素为D与C集合合并 那么合并函数应该具有的功能就是找到C元素所在集合的代表元素然后判断哪个集合大,大集合指向小集合(这是缩短树高减小查询次数,还有压缩路径可以优化时间),那么新集合变为DLKAC,是想要的结果。按这个来写合并函数,后来就会需要findroot函数等。 代码如下 POJ1611

#include <iostream>
int p[300001];//值是对应下标的父节点的下标
int num[300001];

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int set(int x){
    p[x]=x;
    num[x]=1;
    return 0;
}
int findroot(int x){
    int t=x;
    while(p[x]!=x) x=p[x];
    while(p[x]!=x){
    x=p[x];
        p[x]=t;
    }//路径压缩;
    return x;
}
int hb(int a,int b){
    int t=findroot(a);
    int s=findroot(b);
    if(t!=s){
        if(num[t]>=num[s]){
            p[s]=t;
            num[t]+=num[s];
        }else{
            p[t]=s;
            num[s]+=num[t];
        }
    }
    return 0;
}
int main() {
int n,m,k,a,b;
while(~scanf("%d %d",&n,&m),(n!=0||m!=0)){
for(int z=0;z<=n-1;z++){
set(z);
}
while(m--){
    scanf("%d",&k);
    scanf("%d",&a);
    for(int i=1;i<=k-1;i++){
        scanf("%d",&b);
        hb(a,b);
    }
}
printf("%d\n",num[findroot(0)]);
}
    return 0;
}

时间: 2024-10-25 08:46:52

并查集的基本运用 POJ1611的相关文章

poj2236和poj1611并查集问题

POJ 2236 问在计算机坏了,修复若干,问检测两台是否能连通 #include <iostream> #include <string.h> #include <stdio.h> using namespace std; const int N = 1005; struct Point { int x,y; }; Point p[N]; int repaired[N]; int pre[N],rank[N]; int dist(Point A,Point B) {

并查集初学(3)无间道之并查集 &amp;&amp; POJ2542 &amp;&amp; POJ1611

1.hihocoder上面讲的一道题 无间道之并查集 水题,精髓在于使用map容器进行打标签 #include <cstdio> #include <cstring> #include <iostream> #include <string> #include <map> #include <algorithm> using namespace std; const int maxn=10005; int p[maxn]; map&l

poj1611 The Suspects(并查集)

题目链接 http://poj.org/problem?id=1611 题意 有n个学生,编号0~n-1,m个社团,每个社团有k个学生,如果社团里有1个学生是SARS的疑似患者,则该社团所有人都要被隔离.起初学生0是疑似患者,求要隔离多少人. 思路 使用并查集求解. 代码 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int

poj1611 并查集 (路径不压缩)

http://poj.org/problem?id=1611 题目大意: 有一个学校,有N个学生,编号为0-N-1,现在0号学生感染了非典,凡是和0在一个社团的人就会感染,并且这些人如果还参加了别的社团,他所在的社团照样全部感染,求感染的人数. 解题思路: 并查集的变种,实质就是求0所在的强连通图的结点数目. 这道题纠结在数据的输入上,他只是告诉你哪些学生是同一个社团的.这就需要处理一下,我的想法是:如果这个社团有num个孩子,new出一个大小为num的数组,第一个孩子不处理,从第二个孩子起,和

poj1611 简单并查集

The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 32781   Accepted: 15902 Description Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. T

并查集——poj1611(入门)

传送门:The Suspects 并查集水题 #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 50005; int n,m; int a[maxn],b,ans; int pre[maxn]; void init() { for(int i=0;i<n;i++){ pre[i] = i; } } int findPre(

poj1611——The Suspects(并查集)

Description Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others. In t

【并查集】POJ1611 The Suspects

The Suspects Time Limit: 1000MS   Memory Limit: 20000K Total Submissions: 51969   Accepted: 24829 Description Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. T

poj1611(并查集简单应用)

题目链接:http://poj.org/problem?id=1611 思路: 显然是一个并查集的题,很简单,只要将一个group中的学生并在一起,最后遍历1到n-1,看有多少学生的祖先与0的祖先相等即可. 代码如下: 1 #include<cstdio> 2 using namespace std; 3 4 int n,m,res,root[30005]; 5 6 int getr(int k){ 7 if(root[k]==k) return k; 8 else return root[k