并查集

并查集算法是用于查找/分辨 某单个与另某单个是否为同一个群体。
比如,可以通过询问N组的 A B 是否为同一社团,然后问xxxa与xxxb 是否在同一社团。
又或者,可以识别,A与B是朋友 B与C是敌人,那么A与C 因为是敌人的敌人是朋友,所以A与C也是朋友。
也可以在最小生成树的时候,判断2个顶点在不在同一棵树内。
算法模板比较简单。

#define MAXN 1001
int fa[MAXN];
int getFa( int x) {
  return fa[x] == x ? x : fa[x] = getFa(fa[x]);
}
void merge( int a,int b){
  int x = getFa(a);
  int y = getFa(b);
  if ( x != y ){
    fa[x] = y;
  }
}
bool isSame(int a,int b){
  int x = getFa(a);
  int y = getFa(b);
  return x==y;
}

附poj 1182 ac代码

#include <iostream>
#include <cassert>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <cmath>
#include <climits>
#include <functional>
#include <list>
#include <cstdlib>
#include <set>
#include <stack>
#include <map>
#include <algorithm>

using namespace std;

#define FALEN 150015
#define FAHLEN 50005
int fa[FALEN];

int getFah(int a){
	return fa[a] == a ? a : getFah(fa[a]);
}
int getFa(int a){
	int f = getFah(a);
	fa[a] =f;
	return f;
}
void mergeSame(int a,int b){
	int f_a = getFa(a);
	int f_b = getFa(b);
	if ( f_a  != f_b){
		fa[f_a] = f_b;
	}
}

bool isSame(int a,int b){
	int f_a = getFa(a);
	int f_b = getFa(b);
	return f_a == f_b;
}



int main(){
	int ans = 0;
	for( int i=0;i<FALEN;++i ){
		fa[i] = i;
	}
	int N,K;
	scanf("%d%d",&N,&K);
	int D,X,Y;
	for( int i=0;i<K; ++i ){
		scanf("%d%d%d",&D,&X,&Y);
		if ( X > N || Y > N || X < 0 || Y < 0 ){
			++ans ;
		}else{
			if ( D == 1 ){
				if ( isSame(X,Y+FAHLEN) || isSame(X,Y+2*FAHLEN) ){
					ans ++;
				}else{
					mergeSame(X,Y);//链式
					mergeSame(X+FAHLEN,Y+FAHLEN);
					mergeSame(X+2*FAHLEN,Y+2*FAHLEN);
				}
			}else if ( D == 2 ){
				if ( isSame(X,Y) || isSame(X,Y+2*FAHLEN)){
					ans ++;
				}else{
					mergeSame(X,Y+FAHLEN);//链式
					mergeSame(X+FAHLEN,Y+2*FAHLEN);
					mergeSame(X+2*FAHLEN,Y);
				}
			}
		}
	}
	cout << ans << endl;
	return 0;
}

上一篇:牛客提高组模拟4 快速访问——一道树剖“板子”题


下一篇:一些模板