PAT记录2--并差集

  并查集是我的第一个看的L2里面的算法了,还有一个不算算法,就是结构体排序,但在L2里面也有出现,结构体排序了也其实就是贪心,也就是想老师说的贪心悟无处不在,我们一直都在用,只是没有察觉罢了。

  首先附上我已经能背下来了的并查集的主要代码。并查集能解决的问题也肯定是集合的问题了,但也别看到集合就拿这个来做。

上课不好好听课,就写那些去了,额。。。反正老师也没讲什么,哈哈哈哈。

还是把代码粘贴来吧

#include<bits/stdc++.h>
using namespace std;
const int N=11000;
int father[N];
bool isRoot[N];
int findFather(int x) {
	int a=x;
	while(x!=father[x]) {
		x=father[x];
	}
	//压缩路径可以不写          此题不写压缩路径会运行超时,所以必须写,优化代码必须的*** 
	if(a!=father[a]){
		int z=a;        //a要回溯,值会改变,所以用z保存a的值,可以画图更加理解这个过程
		a=father[a];   //a回溯到他的父亲节点
		father[z]=x;    //节点压缩,直接把a的父亲节点指向根节点x;
	}
	return x;
}


void Union(int a,int b) {
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA!=faB) {
		father[faA]=faB;
	}
}

void init(int n) {
	for(int i=1; i<=n; i++) {
		father[i]=i;
		isRoot[i]=false;
	}
}



int main() {
	int n,i,j,k;
	cin>>n;
	int m;
	int num;
	int pre;
	set<int> v;
	set<int>::iterator it;
	init(11000);
	for(i=0; i<n; i++) {
		scanf("%d",&m);
		pre=m;
		for(j=0; j<m; j++) {
			scanf("%d",&num);
			if(j!=0) {
				Union(pre,num);
			}
			pre=num;
			v.insert(num);
		}
	}
//	cout<<"test"<<endl;
//	for(it=v.begin();it!=v.end();it++){
//		cout<<(*it)<<" ";
//	}
//	cout<<endl;


	int a1;
	int in1,in2;
	cin>>a1;
	int res=0;


//	for(i=0;i<a1;i++){
//		cin>>in1>>in2;
//		if(findFather(in1)==findFather(in2)){
//			res+=1;
//		}
//		cout<<"res"<<i+1<<":"<<res<<endl;
//		res=0;
//	}
	int sum=0;
	for(i=1; i<=v.size(); i++) {
//		cout<<"i:"<<i<<"father[i]"<<father[i]<<endl;

		if(father[i]==i) {
			sum+=1;
		}
	}
	cout<<v.size()<<" "<<sum<<endl;


	for(i=0; i<a1; i++) {
		cin>>in1>>in2;
		if(findFather(in1)==findFather(in2)) {
			res+=1;
		}
		if(res==1){
			cout<<"Y";
		}
		else{
			cout<<"N";
		}
		if(i!=a1-1){
			cout<<endl;
		}
//		cout<<"res"<<i+1<<":"<<res<<endl;
		res=0;
	}

	return 0;
}

  并查集只需要看懂三个函数就够了,就是我写在外面的三个函数findFather、Union、init。

  上面的代码是一道完整题目的解,注释的地方是用来测试的,原谅我的电脑不能使用单点调试,一调就崩。。。也好适应正式比赛答题时也是不能调试,只能手动调试。

  这是那一题的题目链接地址如下:上面我写的代码是这题的满分解。点击下方pat题目部落即可查看题目

  pat题目部落

  做题的时候注意要把集合初始化,这是很容易犯的错误,还有就是初始化结合的大小一定要和题目相符,否则做必错,而且还找不到自己错在哪里,我第一没初始化找了半天才看到,未了不让大家走我走过的坑,所以一定记得初始化,而且初始化大小要合适

就比如要像这样初始化。

init(11000);

  这是前几天学的并查集,后面下一篇打算是记录静态链表,昨晚基本已经看懂,再下一篇打算是二叉树的题目,今晚12点前应该能做好,加油!!!

  原谅我写得太直白,太丑,,,,,,

  有广西想去参加CCF的csp认证的吗?有的话留言呀,很想去,但没伴呀,而且题目很难,还要准备数学英语。。。

posted on 2019-03-24 12:07  心所驰  阅读(75)  评论(0)    收藏  举报