并查集-poj2524

以前只知道并查集的原理,并不知道具体实现有那些技巧.

一开始写并查集我把所有点的根全都初始化成0,然后find()等部分都写得很麻烦.

最普遍的写法是把每个点的根都设为自身,这样find就能写的很简便.具体看下面的代码实现

#include <cstdio>
#include <cstring>
int l[60000];
int fd(int a){
    return a==l[a]?a:(l[a]=fd(l[a]));
}
int main(){
    int n,m,a,b,ret,art,brt,t=0;
    while(scanf("%d %d",&n,&m) && n){
        t++;
        ret=0;
        for(int i=1;i<=n;i++){l[i]=i;}
        for(int i=0;i<m;i++){
            scanf("%d %d",&a,&b);
            art=fd(a),brt=fd(b);
            if(art!=brt){
                l[brt]=art;
            }
        }
        for(int i=1;i<=n;i++){
            if(l[i]==i)ret++;
        }
        printf("Case %d: %d\n",t,ret);
    }
}

时间: 2024-12-26 19:56:49

并查集-poj2524的相关文章

poj2524(简单并查集)

#include <iostream>#include <stdio.h>#include <string.h>#include <stdlib.h>using namespace std;int n,m;int bin[50001];int findx(int x){    int r=x;    while(r!=bin[r])        r=bin[r];    int j=x,k;    while(j!=r)    {        k=bin

并查集水题 POJ2524

题意:一所学校有有n个学生,询问m对学生的宗教是否相同,求出这所学校最多有多少种宗教. 把宗教相同的学生连一条边,则未询问的学生默认他们没有边,最后连通块的个数就是宗教最多有多少个,并查集实现,把每个节点的最终父节点存到数组里,数组里不同元素的个数即为连通块的个数. 代码:

【POJ-2524】Ubiquitous Religions(并查集)

并查集. #include<cstdio> #include<cstring> using namespace std; const int maxn = 55555; int fa[maxn]; int vis[maxn]; int n,m,t; void init(){ for(int i = 0; i < n; i++) {fa[i] = i;} memset(vis,0,sizeof(vis)); } int find_father(int u){ return fa

poj2524(并查集水题)

题目链接:http://poj.org/problem?id=2524 题目大意:学校共有n个同学,告诉你m对同学信仰同一宗教,问这个学校学生信仰宗教的数目最多为多少. 例: Sample Input 10 91 21 31 41 51 61 71 81 91 1010 42 34 54 85 80 0 Sample Output Case 1: 1Case 2: 7 解题思路:直接套并查集的板子就可以了,初始化n个集合默认他们都信任不一样的宗教,初始就用n个宗教,每次给你的两个同学那个号码将他

详解并查集

详解并查集  Powered by WSY in SSF    2019-11-02  13:46 [1]并查集的定义:   并查集(Disjoint  Set)是一种非常精巧的非常实用的数据结构,它主要用来处理一些不相交集合的合并问题,经典的例子有联通子图,最小生成树的克鲁斯-卡尔算法. [2]并查集的经典问题:   我们通常使用“帮派”.“团伙”等问题举例说明并查集.例如帮派问题: 在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足: 1. 我朋友的朋友是我的朋友: 2. 我敌

CodeForces 745C Hongcow Builds A Nation 并查集

题意: 给了你n个城市 m条边 k个政府 每个政府管辖的区域内不能和其他政府的区域有相连 即政府之间不存在路径 问你在维护这种关系的同时 最多再加多少条边 思路: 先找出来每个联通块 再找出来没有归属的孤立的点 把他们都放到最大的联通块里 然后每个联通块之间的点两两连边是n*(n-1)/2条边 最后算出来的ans-m就好了 (看别人的博客学了一个max_element 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a

并查集(个人模版)

并查集: 1 int find(int a) 2 { 3 int r=a; 4 while(f[r]!=r) 5 r=f[r]; 6 int i=a; 7 int j; 8 while(i!=r) 9 { 10 j=f[i]; 11 f[i]=r; 12 i=j; 13 } 14 return r; 15 } 16 int merge(int a,int b) 17 { 18 int A,B; 19 A=find(a); 20 B=find(b); 21 if(A!=B) 22 { 23 f[B

并查集应用

题目描述: One way that the police finds the head of a gang is to check people's phone calls. If there is a phone call between A and B, we say that A and B is related. The weight of a relation is defined to be the total time length of all the phone calls

【bzoj3674】 可持久化并查集加强版

http://www.lydsy.com/JudgeOnline/problem.php?id=3674 (题目链接) 题意 维护并查集3个操作:合并:回到完成第k个操作后的状态:查询. Solution 其实就是用主席树的叶子节点维护并查集的可持久化数组fa[]. 细节 终于认识到了按秩合并的强大,单纯写个路径压缩Re飞,写了路径压缩+按秩合并比单纯的按秩合并每快多少→_→ 代码 // bzoj3674 #include<algorithm> #include<iostream>