您的位置:首页 > 其它

HDU - 1213 How Many Tables

2018-01-23 20:47 453 查看
to meet those who hate English ,this article is wrote by Chinese.

题目分析

这道题就是裸的并查集,那么什么是并查集呢?

并查集是算法大牛tarjan老爷子的杰作,很多人认为并查集是世界上最优美的数据结构之一。并查集保存了一个节点的父节点信息。我们用一个数组来保存一个节点的父节点。再初始的时候,每个节点都是自己的父节点。

下面我们来说说第一个操作,也就是找到自己的父节点:very simple,对于一个节点的父节点,这个节点的父节点一定是自己。我们可以沿着父节点数组一直到结束。之后将这条路径上的所有点都纳入我们找到的父节点的范围内。

第二个操作我们一般叫merge:so ez,对于两个待操作的节点,我们将第二个节点的父节点变成第一个节点的父节点就可以了。

这两个操作的意义在于维护每个节点的一种“属性”,如果我们需要让具有相同属性的节点聚在一起时,也就是要维护每个节点的从属关系时,这种信息就十分重要了。

回到题目,题目要求我们寻找朋友圈子的个数,也就是具有相同属性:是X的朋友的聚类的个数,同时这个朋友关系满足传递关系,那么我们就可以用并查集来实现。将具有朋友关系的两个节点merge一下。最后统计父节点是自己的节点个数就行。

#include<bits/stdc++.h>
#include <string>
#define MAX_SIZE 1005
int pa[MAX_SIZE];
using namespace std;
void init()
{
for(int i = 1; i <= MAX_SIZE; i++)
{
pa[i] = i;
}
}
int findset(int v)
{
int t1,t2=v;
while(v!=pa[v])
v=pa[v];
while(t2!=pa[t2])
{
t1=pa[t2];
pa[t2]=v;
t2=t1;
}
return v;
}
void Union(int a, int b)
{
int a1 = findset(a);
int b1 = findset(b);
if(a1 != b1)        //这个判定条件可选,主要是为了防止findset路径压缩的时候出现死循环
{
pa[a1] = b1;        //如果存的是有向图,并且做题时集合中元素的顺序很重要,不能忽略,那么这里应该用"pa[a] = b;"
}
}

int main(int argc, char** argv)
{
int ca=0;
cin>>ca;
while(ca--)
{
init();
int n=0,m=0;
cin>>n>>m;
int t1,t2;
for(int i=0;i<m;i++)
{
cin>>t1>>t2;
Union(t1,t2);
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(pa[i]==i)
{
ans++;
}
}
cout<<ans<<endl;
getchar();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: