并查集:是数据结构里面比较简单的一种~~
稍微看看,你应该就会懂,现在我来总结一下,
并查集,是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。
如果忘了,可以看自己的收集的资料~~不多讲述.
入门题:
hdu 1232 1272 1274 1213 1856
现在详细讲解一下,省的到时候忘记了~~
hdu 1232 入门题
#include <iostream>
#include <cstdio>
using namespace std;
int pow[1001];
int sum;
int find(int r) //查找
{
int i=r,j;
while(pow[r]!=r)
r=pow[r];
/*
while(i!=r) //路径压缩
{
j=pow[i];
pow[i]=r;
i=j;
} */
return r;
}
void unions(int x,int y) // 合并
{
int a=find(x);
int b=find(y);
if(a!=b){
pow[a]=b;
sum--;
}
}
int main()
{
int n,m;
int x,y;
while(cin>>n,n)
{
cin>>m;
sum=n-1;
for(int i=1;i<=n;i++)
pow[i]=i;
for(int i=0;i<m;i++){
// cin>>x>>y;
scanf("%d%d",&x,&y);
unions(x,y);
}
cout<<sum<<endl;
}
return 0;
}
hdu 1272
#include <iostream>
using namespace std;
int pow[100001];
bool vis[1001][1001];
int sum(0);
int finds(int r)
{
while(r!=pow[r])
r=pow[r];
return r;
}
void unions(int x,int y)
{
int a=finds(x);
int b=finds(y);
if(a!=b)
pow[a]=b;
}
int main()
{
int x,y;
int max(0);
memset(vis,0,sizeof(vis));
for(;;)
{
cin>>x>>y;
if(x==y==-1) break;
if(x==y==0){
sum=max-1;
for(int i=1;i<=max;i++)
pow[i]=i;
for(int i=1;i<=max;i++)
for(int j=1;j<=max;j++)
if(vis[i][j]){
unions(i,j);
sum--;
}
cout<<sum<<endl;
max=0;
memset(vis,0,sizeof(vis));
}
vis[x][y]=1;
if(max<x) max=x; if(max<y) max=y;
}
return 0;
}
hdu 1213
#include <iostream>
using namespace std;
int pow[1001];
int sum;
int find(int r)
{
while(r!=pow[r])
r=pow[r];
return r;
}
void unions(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b){
pow[a]=b;
sum--;
}
}
int main()
{
int t;
int m,n;
cin>>t;
while(t--)
{
int x,y;
cin>>n>>m;
sum=n;
for(int i=1;i<=n;i++)
pow[i]=i;
for(int i=0;i<m;i++)
{
cin>>x>>y;
unions(x,y);
}
cout<<sum<<endl;
}
return 0;
}
hdu 1274
#include <iostream>
using namespace std;
const int size=100000;
int low[100001];
bool vis[100001];
int find(int r)
{
while(r!=low[r])
r=low[r];
return r;
}
bool unions(int x,int y)
{
int a=find(x);
int b=find(y);
if(a==b) return 0;
else {
low[a]=b;
return 1;
}
}
int main()
{
int a,b;
int max(0),sum(0);
while(cin>>a>>b,a!=-1&&b!=-1)
{
if(a==0&&b==0){
cout<<"Yes"<<endl;
continue;
}
bool f=1;
max=a>b?a:b;
for(int i=1;i<=size;i++)
low[i]=i;
memset(vis,0,sizeof(vis));
vis[a]=vis[b]=1;
if(unions(a,b))
while(cin>>a>>b,a+b){
if(!unions(a,b))
f=0;
vis[a]=vis[b]=1;
if(max<a) max=a;
if(max<b) max=b;
}
sum=0;
for(int i=1;i<=max;i++)
if(low[i]==i&&vis[i])sum++;
if(f&&sum==1)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
这一题得吐槽一下,这个输入0的时候得输出1,还有数据比较大得优化~~
优化方法有两种迭代和循环~~
这题wa了好多次~~一个小错误害死我了
int a[4],我取了个i=4悲剧了
#include <iostream>
using namespace std;
const int size=10000001;
int pow[size];
int cus[size];
int findsum;
int find(int r)
{
int i=r,j;
if(r!=pow[r]) //迭代优化
pow[r]=find(pow[r]);
return pow[r];
/*
while(r!=pow[r]) // 循环优化(优化也就是路径压缩)
r=pow[r];
while(i!=r)
{
j=pow[i];
pow[i]=r;
i=j;
}
return r;*/
}
void unions(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b){
pow[a]=b;
cus[b]+=cus[a];
if(cus[b]>findsum)
findsum=cus[b];
}
}
int main()
{
int t;
while(cin>>t)
{
int x,y;
findsum=1;
for(int i=1;i<size;i++){
pow[i]=i; cus[i]=1;
}
for(int i=0;i<t;i++)
{
cin>>x>>y;
unions(x,y);
}
cout<<findsum<<endl;
}
return 0;
}
还有一种做法,一开始就应该ac的可惜 i=size i取了等号 ,找了好久没发现,然后看了别人ac的代码,写了第一种方法~~
#include <iostream>
using namespace std;
const int size=10000001;
int pow[size];
int cus[size];
int find(int r)
{
int i=r,j;
while(r!=pow[r])
r=pow[r];
while(i!=r)
{
j=pow[i];
pow[i]=r;
i=j;
}
return r;
}
void unions(int x,int y)
{
int a=find(x);
int b=find(y);
if(a!=b){
pow[a]=b;
cus[b]+=cus[a]; // cus[a]=0; 有没有无关紧要
}
}
int main()
{
int t;
while(cin>>t)
{
int x,y;
int sum(0),findsum(1);
for(int i=1;i<size;i++){
pow[i]=i; cus[i]=1;
}
for(int i=0;i<t;i++)
{
cin>>x>>y;
if(sum<x) sum=x;
if(sum<y) sum=y;
unions(x,y);
}
for(int i=1;i<=sum;i++)
if(findsum<cus[i]) findsum=cus[i];
cout<<findsum<<endl;
}
return 0;
}
好了现在哦了,看完了 并查集,该看其他的算法了~~