第九周 并查集

并查集总结:

#define N 
int f[N];
void init(int k){
	for(int i=1;i<=k;i++)
		f[i]=i;
}
int find(int k){
	if(k==f[k])
		return k;
	return f[k]=find(f[k]);
}
void Union(int a,int b){
	int fa=find(a);
	int fb=find(b);
	if(fa!=fb)
		f[fa]=fb;
}

1. 判断元素个数,集合个数之类

        有几个这个就有几个集合

if(find(i)==f[i])
    sum++;

         元素的个数==同个根节点下有几个孩子

isRoot[find(i)]++;

2. 判断环

3. 需要加几条边能构成一个连通块

这两类问题主要是在 Union 函数中添加操作来实现。

判断环:

        a,b之间的根节点如果相同=》a,b是联通的=》a,b之间已经存在了一条路了

       当我们又添加了一条路的时候,就说明图中出现了环。

if(fa!=fb)
		f[fa]=fb;
else
    出现了环

2492 -- A Bug's Life (poj.org)

需要加几条边能构成一个连通块:

        当sum=n-1时就成连通块了,

	if(fa!=fb){
		f[fa]=fb;
		sum++;
	}

前三类问题只要出现 集合,连接,集合中元素的个数 就往并查集想。

一般都会加一些限制:

        合并时需要代价:

                1. 要求达到效果(连通)时,所有消耗的代价的最大值最小。

                实现:排序后,从小到大,在到达效果前无限加(都加进去)。

      P1111 修复公路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

                2. 要求达到效果(连通)时,所有消耗的代价的和的最小值。

                实现:排序后,从小到大,只合并需要合并的(不能出现环)。                

void Union(int a,int b,int c){
	int fa=find(a);
	int fb=find(b);
	if(fa!=fb){ 
		sum1++;//记录合并的次数 
		sum2+=c;// 能合并,才加上代价
		f[fa]=fb;
	}
}

P1195 口袋的天空 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

        代价问题的核心都是按代价排序

         一般用结构体存两点和代价

struct Node{
	int x;
	int y;
	int t;
}ans[N];
bool cmp(const Node &a,const Node &b){
	return a.t<b.t;
} 

        将数字换成字符串:

                 因为 f[i] 数组的值等于 i 数值时才判断是根节点,所以出现字符串的时候,我们就无法用数组来实现并查集。

map <string,string> f;

                需要注意的是:如何初始化。当一个字符串是第一次出现的判断条件(当我们没有给字符串s 找“爹”时,它的“爹”是 "")是 

f[s]==""

P2814 家谱 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

4. 带值并查集

        1.需要树的高度。

                用 rank[] 存高度,高的在低的上面(高的树是低的树的根节点);

void union(int x,int y)
{
    x=find(x);							//寻找 x的代表元
    y=find(y);							//寻找 y的代表元
    if(x==y) return ;					//如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,直接返回;否则,执行下面的逻辑
    if(rank[x]>rank[y]) pre[y]=x;		//如果 x的高度大于 y,则令 y的上级为 x
    else								//否则
    {
        if(rank[x]==rank[y]) rank[y]++;	//如果 x的高度和 y的高度相同,则令 y的高度加1
        pre[x]=y;						//让 x的上级为 y
    }
}
————————————————
版权声明:本文为CSDN博主「酱懵静」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/the_ZED/article/details/105126583

        2. 带权的。

                 可以用于判断最小环和其他想不到 的问题               

int find(int k)
{
	if(k!=f[k])
	{
		int t=f[k];
		f[k]=find(f[k]);
		value[k]+=value[t];
	}
	return f[k];
}
void Union(int a,int b){
		int fa=find(a);
		int fb=find(b);
		if(fa!=fb)
		{
			f[fa]=fb;
			value[fa]=-value[a]+value[b]+(a到b的权值);
		}
}

 

P2661 [NOIP2015 提高组] 信息传递 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

P6691 选择题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

5. 逆向思维

        并查集无法实现拆分

        所以当我们需要拆路去处理并查集相关的问题(连通块,集合个数等)时,我们可以反向操作。用一个数组去存差点(路)的顺序(离线操作),然后当我们反向去处理问题的时候,就变成了合并。

        一般与图论相关的知识有关。

        因为要离线操作,我们就需要存图,存数据。

        P6121 [USACO16OPEN]Closing the Farm G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 

6. 特殊点

        特殊点与集合的关系

        1. 求集合中同时有两个点的个数

                当满足条件时,用新的 f[] 记录。

P3958 [NOIP2017 提高组] 奶酪 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

7. 种类 

P1892 [BOI2003]团伙 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

并查集不难用,在题目怎么看出来才难。

 

 

学的太慢。

应该先把题目和题解都看完,再去敲。

先总整体上把控一下一个知识点有几种题型,再想一下难易程度,然后按照难易分配不同的时间去做题。

心态太容易炸了,每次遇到不会的题就开始摆烂,不去耐着心思继续读题。眼高手低,每次都想成为最好的,一有错就想等下次比赛从新来过。殊不知,没有失败就不会有成功。

费老师说搞他这个就把其他的都放下,确实,我心里撑不住事情,一有事就会去想,担心那件事如何如何的,但是我不敢把其他的东西放下,太怂了,不想没有退路,更多的是没有信心能把事情做好。其实现在啥都弄好,看他们有,就想要,却又付出不了那种汗水。

讲真的,学习算法的时候,每次看懂一个知识点,是很开心的。但看到别人弄个小游戏,写个爬虫,做个网页也挺羡慕的,就是太贪心了。

每次事情一多,我首先不是想如何去解决,而是去逃避,拿手机看一会,去睡一会觉,去洗个澡,发个呆。

需要回扣总结的东西有很多,但是一直懒得总结,总给自己找没有时间的理由。

上学期acm协会的宣传的时候,了解到了算法,感觉很酷很好玩。当时就跟着做了一下洛谷提单前面几个简单的模块,但也因为一些其他的事没有坚持下来。新生赛时,看到有很多人能把自己看都看不懂的题a出来,当时还以为他们高中的时候就学过,现在才知道,他们是上了大学才开始学的。问过第一名怎么学的,他舍友说,他就是做题,哪里不会,就去搜资料,然后去学习。这一点和费老师说的一样,我一直认为这样学的不系统,感觉长期以往的话,会不扎实,现在看来,是我错了,更主要的是我没有他那种专注。去过他宿舍,他遇到不会的东西就去学,不会管其他的,心无旁骛。每次周围有人说什么话,我都会受别人说的话影响。再后来,想要跟着费老师学习,然后想去打个比赛,只是因为喜欢。高中过的太混了,大学不想混了。上学期问了很多关于算法课的问题。当选课时,发现我的课和费老师的课冲突的时候,报不上了,感觉心里空荡荡的。最后几经周折,好不容易报上了,但经过那种就是,颓废,然后落下作业,看到别人的进步,没有激励到我,反而是嫉妒,每次都忽略别人的付出。现在课快结束了,初心也快忘了。

大一嘛,每个人想去尝试一些新鲜的东西。之前一起上算法课的同学,很多都报了其他的东西,我也是。但他们现在都,都退了,他们敢孤注一掷的勇气,是我羡慕,但做不来的。有些人可以同时可以干很多事,我以为我也是,可惜并不是如此。我不知道我该去做什么,我想去寻找最优解,但最优解一定不是现在。

我以为我够认真了,只是效率不高,结果今天才发现,一块上课的同学,一直都比我起的早,回来的晚。拼效率拼不过,现在拼时间也拼不过。

想以后跟着费老师继续搞下去,之前是,现在也是,但现在的状态肯定是不可以的。

时间不多了。

 

---------------------------------------------------------------------------------------------------------

睡不着,在床上想结课后,我的总结会怎么去写呢。不能留下遗憾。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值