您的位置:首页 > 其它

HDU - 1213有意思的并查集/"掌门"

2018-02-07 10:13 309 查看
深夜未耕
【一个典型的并查集】

参考网址:http://blog.csdn.net/u013546077/article/details/64509038

借用了里面的掌门学说注释这道题

#include <iostream>
using namespace std;

int pre[1010];
//你不知道吧  我一个人在寝室 放着杨千嬅的小星星 对面你发来一句话  我对着屏幕空空地说
//"我喜欢你!"
//"我喜欢你你听到了吗  听不到也没关系 我在慢慢像你靠近"
int find(int x)
{(讲成爸爸似乎不太好理解,按括号里的掌门理解)
int r = x;//对r说,你快去找爸爸(找我们掌门)
while (pre[r] != r)//pre里面存的是谁是谁的爸爸,如果他爸爸不是自己的话(不是祖先(pre里面存的是谁是谁的掌门)
r = pre[r];
//那r变成r的爸爸,r的爸爸再去找他的爸爸
//(不不不,r再去找r上面那一层,直到最后找到的就是自己是掌门为止--终极掌门哈哈哈)
int i = x, j;
//路径压缩...  (就这么简单吗?? 并查集)

//这个记录一下啊,查询路径里面,问了这么多人,这么多人
//x先赋值给i: 从x以及更多的x(下面表现为不断更替的r)都想知道
while (i != r)//当i还没变成最终掌门的时候,就继续往下循环ing
{
j = pre[i];//
pre[i] = r;
i = j;
}
//i=x;i的直属掌门是pre[i],也正好是路径压缩里面下一个需要重新皈依门派的人;r赋值给pre[i],就是让i明白终极掌门是r,在pre[]这个记录掌门是谁的数组里面存一下;最后j的值(pre[i]的值)给i,也就是路径压缩里面下一个需要重新皈依门派的人,继续这个循环,一路上问过的人他们的终极掌门都是r,最后返回r

return r;//最后返回的是他们最终的掌门.jpg
}

int main()
{
int n, m;
int t;
cin >> t;
while (t--)//最开始的t仅仅代表输入   -- 输入了多少个而已
{
int total;
cin >> n;
for (int i = 1; i <= n; i++)
pre[i] = i;//并查集的初始化:最开始他们都是自成一家的,自己是自己的掌门
total = n;
cin >> m;
int p1, p2, f1, f2;
while (m--)
{
cin >> p1 >> p2;
f1 = find(p1);
f2 = find(p2);
//从一开始,他们都自己是自己的掌门,当发现他们不是一家子的时候,这两人要结拜兄弟
//并且,不是这样的话,f1和f2都是(各自门派里)的终极掌门
//这样继续向下,让f2的掌门认成f1,下面的也都连接了起来
//也就是pre[f2] = f1;
if (f1 != f2)
{
pre[f2] = f1;
total--;
}
}
cout << total << endl;
//因为有重复 的呀,如果重复total就不会减了,知道本来最开始 有多少人很重要。
}
return 0;
}

【另外】自己上手打了一遍,还有两个要注意:

数组稍微开大一点

for (int i = 1; i <= n; i++)
pre[i] = i;这里是从1开始的(好习惯?emmm)
因为编号这种东西并不会智能到从0开始  注意一下

//吐槽.....这个题怎么这么干的并查集,还是只有25A= =

// 从寒假开始第一场*64的人到现在只有 *32..还是要善始善终呀

//你看..我只要有环境,简直是无所不能啊!

// 在寝室里一个晚上都没搞好的东西....来到机房锁手机十分钟写完了  还是需要个人监督我0 0今天是和她约了早起 
//加油啦!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: