第十三次
开并查集已经三个周了,前两个周老师讲的知识点,还有就是自己看一些博客和并查集的例题。这个周的主要内容就是写一些并查集的例题。老师上个星期发了一个文档,里面大概五十多道题目,我这个星期主要就是看这个里面上的题目。
并查集的题目确实比搜索简单,但是就像老师说的,有的题目很难想到用并查集的题目来写,如果不是因为老师将他放在并查集的文档里面,或许我根本想不到用并查集。
这些题目确实比搜索简单,而且老师安排的文档好友顺序,前面好多简单的题目,但是越往后写,好多题的题目都要看不懂了。后面的题目好多不看题解根本想不出来怎么写的。
下面说一下我对看的这些题目的总结吧:
1、连通问题:这一类问题就是找出俩点之间最小代价或者最大代价。具体的就看上一篇博客吧。
2、最小生成树:最小生成树(即可以通过n-1条边,所有边的代价和最小连通全部的点)。这一类问题感觉和上面的连通问题差不多,因为牵扯到大小关系,所以需要对边的权值进行排序,然后依次增加边,如果增加的边的俩个点的父结点已经一样,那么不必再将这个边加入。如果不一样,则需要将这个边加入,加入也就是将这俩个点的父结点设置为一样,然后让jishu加1(jishu的初始值为1)。接下来就是一直加边,直到jishu==n。这个就代表全部的点已经相连。(下面代码里面的shuliang和我说的jishu等价),然后就是里面的ans记录的最小生成树的所需的最小代价和(有的题目可能不需要,有的只需要记录下俩最后一个最大的)。
int shuliang=1;
int ans=0;
for(int i=1;i<jishu;i++){
int a=find(e[i].x);
int b=find(e[i].y);
if(a!=b){
fa[a]=b;
shuliang++;
ans+=e[i].juli;
}
//else
// shuliang++;
if(shuliang==n){
break;
}
}
cout<<ans<<endl;
下面的题目都是关于最小生成树的:
[USACO3.1]最短网络 Agri-Net - 洛谷 |
[USACO05MAR]Out of Hay S - 洛谷 |
无线通讯网 - 洛谷 |
[SCOI2005]繁忙的都市 - 洛谷 |
就是这个无线通讯网的题目,需要注意一下,这个不需要实现全部的连通(n-m+1即可),因为还有电话可以实现远程信息传输。但是写代码的时候将cout<<ans<<endl;放错了位置,一直过不了。放在下面才有输出了(但是我到现在也不知道是什么原理)。
3、查找关系:这一类题目就是先建立好集合,然后查找俩个点之间的关系。这一类题目确实挺简单的,但是有的题目查找的是名字,那么就需要用字符串来写。我就是建了一个map<string,string>fa;来保存这些数据。
map<string,string>fa;
string find(string x){
if(x!=fa[x])
fa[x]=find(fa[x]);
return fa[x];
}
for(int i=1;i<=m;i++){
cin>>a>>b;
string x=find(a);
string y=find(b);
if(x!=y){
fa[x]=y;
}
}
家谱 - 洛谷 |
一中校运会之百米跑 - 洛谷 |
朋友 - 洛谷 |
上面这些题目几乎都是找集合里面的关系。
4、再矩阵中:这一类问题再矩阵中,俩个相邻的点之间都有一定的权值,就相当于那些边。接下来的处理就和之前的差不多。不过,这一类的题目我几乎没有写多少,因为感觉它们太难了。但是就是大概看了这些。
5、与环有关:有的题目要求找出环,有的题目要求拆除环,那么都需要先找出环,找出环的话,就是一直加入边(不同的题目可能加入边的顺序不一样),然后就是判断加入的边的俩个点的父结点是否一样,如果一样,那么加入后一定会形成环。则这个边就是解题的关键了。
[NOIP2015 提高组] 信息传递 - 洛谷 |
这个题目,我看题解之间都没有想到要用环,只要找到环,就代表这个人从别人嘴中知道了自己的生日。即满足题目要求。但是注意要找最小的。
局域网 - 洛谷 |
这个题,尽量拆边大的,所以需要对边排序后,再加入。
以上就是这些题目的总结了。这一周后,并查集就要结束了。开始新的专题了。