虽说在学校做了不少的ACM题目。不过都是自己乱搞的。没有什么章法。
现在继续搞算法。要分门别类的学好算法。
惭愧得很现在才开始学习并查集。而且还是这么入门级的。。。我要一点一点的记录自己的进步。
并查集的介绍网上到处都是,话说我也是在网上找网友的介绍学习的。所以就不再多说了。
最简单的并查集:POJ 1611 the suspect
#include <iostream>
using namespace std;
using namespace std;
int pre[30002],num[30002];
void Initi(int n)//并查集基本操作:初始化;
{
for(int i=0;i<n;i++)
{
pre[i]=-1;num[i]=1;
}
}
{
for(int i=0;i<n;i++)
{
pre[i]=-1;num[i]=1;
}
}
int Find(int x)//并查集基本操作:确定x所属的集合;
{
int r=x;int p;
while(pre[r]!=-1)
{
r=pre[r];
}
while(x!=r)//路径压缩
{
p=pre[x];
pre[x]=r;
x=p;
}
return r;
}
{
int r=x;int p;
while(pre[r]!=-1)
{
r=pre[r];
}
while(x!=r)//路径压缩
{
p=pre[x];
pre[x]=r;
x=p;
}
return r;
}
void Union(int a,int b)//基本操作:合并两个集合(不相交的集合)
{
int r1,r2;
r1=Find(a);r2=Find(b);
if(r1==r2) return ;
if(num[r1]<num[r2])
{
pre[r1]=r2;
num[r2]+=num[r1];
}
else
{
pre[r2]=r1;
num[r1]+=num[r2];
}
}
{
int r1,r2;
r1=Find(a);r2=Find(b);
if(r1==r2) return ;
if(num[r1]<num[r2])
{
pre[r1]=r2;
num[r2]+=num[r1];
}
else
{
pre[r2]=r1;
num[r1]+=num[r2];
}
}
int main(void)
{
int n,m,k,j,a,b;
{
int n,m,k,j,a,b;
while(cin>>n>>m)
{
if(n+m==0) break;
Initi(n);
while(m--)
{
cin>>k;
cin>>a;
a=Find(a);
for(j=1;j<k;j++)
{
cin>>b;
b=Find(b);
Union(a,b);
}
}
cout<<num[Find(0)]<<endl;//找到0 所在的集合有多少个元素即为题目答案;
}
return 0;
}
{
if(n+m==0) break;
Initi(n);
while(m--)
{
cin>>k;
cin>>a;
a=Find(a);
for(j=1;j<k;j++)
{
cin>>b;
b=Find(b);
Union(a,b);
}
}
cout<<num[Find(0)]<<endl;//找到0 所在的集合有多少个元素即为题目答案;
}
return 0;
}