1. 程式人生 > >並查集 poj 1182 食物鏈

並查集 poj 1182 食物鏈

首先,並查集是一種來管理元素分組情況的資料結構。時間複雜度為O(a(n))//阿克曼函式的反函式,比O(log(n))還要快。

這題先用基礎的方法來看,先介紹並查集的基本形式(模板型別):

初始化:

void Init(int n){ 
	for(int i = 1;i <= n*3; ++i){
		par[i] = i;//各點本身的父節點初始化本身 
		rank1[i]=0;//各個點的高度為0;有的編譯器直接定義rank會報摸稜兩可

	}
}

最開始無邊。

合併:(為了防止退化)

合併時對於兩棵樹rank不同,那麼從rank小的向rank大的連;

通過路徑壓縮,使查並集更高效。對於每個節點,直接與他的根節點相連線,這種情況,為了簡單,即使樹的高度發生變化,也不修改rank的值(本題);

void Unite(int x,int y){//合併x,y類; 
	x = Find(x);
	y = Find(y);
	if(x == y) return;
	if(rank1[x] < rank1[y])
		par[x] = y;
	else{
		par[y] = x;
		if(rank1[x] == rank1[y]) rank1[x]++; 
	}
}

查詢:

找到兩個點是否是同一組

int Find(int x){
	return x ==par[x] ? x : Find(par[x]);//查詢x的祖宗;	
}

bool Same(int x,int y){//判斷x,y是否是同一類(同一祖宗) 
	return Find(x) == Find(y);
}

分割線

本題這種方法巧妙在他對3種關係同時進行了管理,化空間為時間。

//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int maxn = 500010;//陣列因為是n 3倍,所以還是儘量開大點; 
int par[maxn];//父節點 
//int rank1[maxn];//高度 

void Init(int n){ //並查集初始化 
	for(int i = 1;i <= n*3; ++i){
		par[i] = i;//各點本身的父節點初始化本身 
		//rank1[i]=0;
	}
}

int Find(int x){
	return x ==par[x] ? x : Find(par[x]);//查詢x的祖宗;	
}

void Unite(int x,int y){//合併x,y類; 
	x = Find(x);
	y = Find(y);
	if(x == y) return;
		par[x] = y;
}

bool Same(int x,int y){//判斷x,y是否是同一類(同一祖宗) 
	return Find(x) == Find(y);
}

int N,K;
int main(){
	//ios::sync_with_stdio(false); 這題好像不吃關閉輸入流 ,所以還是老老實實scanf; 
	cin>>N>>K;
	int ans = 0;
	Init(N*3);//初始化3段,0-N代表x->A(x是A類),N~2N,代表x->B,2N~3N,代表x->C;分3段管理 
	for(int i = 0;i<K; ++i){
		int t,x,y;
		//cin>>t>>x>>y;
		scanf("%d%d%d",&t,&x,&y);//老老實實scanf; 
		
		if(x<=0 || N<x || y<=0 || N<y){//可直接判斷錯誤的條件,小於0或大於N 
			ans++;continue;
		}
		if(t == 1){//合併類,先判斷,同類 
			if(Same(x,y+N) || Same(x,y+2*N)){//如果找到x,y是不同類,錯誤 
				ans++;
			}
			else{
				Unite(x,y);//因為x,y是同類,所以x+N和y+N是同類; 
				Unite(x+N,y+N);
			    Unite(x+N*2,y+N*2); 
			}
		}
		else{//x吃y 
			if(Same(x,y) || Same(x,y+2*N)){//如果找到x和y是同類或者x被y吃 ,錯誤 
				ans++;
			}
			else{
				Unite(x,y+N);//同理 
				Unite(x+N,y+2*N);
				Unite(x+2*N,y);
			}
		}
	}
	cout<<ans<<endl; 
	return 0;
}

這題還有向量思維模式 ,(2);

最後:

programming is the most fun you can have with your clothes on.