题目:对于集合S={1,2,3,4,5,6,7,8,9,10,11,12,13}:依次读入若干等价对1三5,2三3……等价对中的数属于同一个集合,现在需要编程识别等价对1将集合S划分成几个子集和
输出:
3 //3个等价对
1 5‘
2 3
5 8
输出:
1 5 8
2 3
这道题可以用图的遍历 输出 但是如果集合S的数量非常庞大 用图就会内存不足
省内存的话用并查集即可
# include <stdio.h>
# define N 100000001
int p[N],y;
int C[N];
int tree[2*N],num;
void Dsort(int *tree,int n);
int find(int x);
void Link(int x,int y);
int main()
{
int i,j,k,l,m,n;
//freopen("AAA.txt","r",stdin);
while(~scanf("%d",&n))
{
for(i=0; i<n; i++)
{
scanf("%d%d",&j,&k);
Link(j,k);
}
Dsort(tree,num);
for(i=m=k=0; i<num; i++)
if(p[tree[i]])
{
for(j=i,l=find(tree[i]); j<num; j++)
if(p[tree[j]]&&find(tree[j])==l)
{
C[k++]=tree[j];
printf("%d ",tree[j]);
}
while(m<k)p[C[m++]]=0;
C[k++]=0;
printf("\n");
}
num=0;
}
return 0;
}
int find(int x)
{
y=x;
if(p[x])while(x!=p[x]) x=p[x];
else tree[num++]=x;
return p[y]=x;
}
void Link(int x,int y)
{
p[find(x)]=find(y);
}
void Dsort(int *tree,int n)
{
int i,j=1,L,R;
tree--;
while((i=++j)<=n)
{
R=tree[i];
while(i>1)
{
L=(i>>1);
if(tree[L]>=R) break;
tree[i]=tree[L];
i=L;
}
tree[i]=R;
}
while(n)
{
R=tree[n];
tree[n--]=tree[1];
i=1;
L=2;
while(L<=n)
{
L+=L<n&&tree[L+1]>tree[L];
if(tree[L]<=R) break;
tree[i]=tree[L];
i=L;
L<<=1;
}
tree[i]=R;
}
}
# include <stdio.h> //用优先队列 时间开销小
# define N 1000001
void insert(int Tree[],int X);//向堆中插入值 S[WEI]
int Delmin(int Tree[]); //删除堆头-并返回堆头
int find(int x);
void Link(int x,int y);
int tree[N+1]; //堆
int p[N],Q[N],C[2*N];
int main(){
int i,j,k,l,m,n;
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&j,&k);
if(find(j)!=find(k))
Link(j,k);
}
n=0;
while(tree[0])Q[n++]=Delmin(tree);
for(i=m=k=0;i<n;i++)
if(p[Q[i]])
{
for(j=i,l=find(Q[i]);j<n;j++)
if(p[Q[j]]&&find(Q[j])==l)
{
C[k++]=Q[j];
printf("%d ",Q[j]);
}
while(m<k)p[C[m++]]=0;
k++;
printf("\n");
}
return 0;
}
void insert(int Tree[],int X)//向最小堆中插入X
{
int par,i=++Tree[0]; //插入X 后 Tree[0]+1
while(i>1) //直到i不是根节点
{
par=(i>>1); //父节点为par
if(Tree[par]<=X) break; //将<=改为>=即改为最大堆了
Tree[i]=Tree[par]; //否则调整堆 即位置上移
i=par;
}
Tree[i]=X; //插入新节点
}
int Delmin(int Tree[])
{
int i=1,L=2,root=Tree[1],X=Tree[Tree[0]--];
while(L<=Tree[0])
{
L+=L<Tree[0]&&Tree[L+1]<Tree[L];
if(Tree[L]>=X) break;
Tree[i]=Tree[L];
i=L; L=i<<1;
}
Tree[i]=X;
return root;
}
int find(int x)
{
if(!p[x])
{
p[x]=x;
insert(tree,x);//进堆
}
while(x!=p[x]) x=p[x];
return x;
}
void Link(int x,int y)
{
int fx=0,fy=0;
if(!p[x]) p[x]=x;
if(!p[y]) p[y]=y;
while(x!=p[x]&&++fx) x=p[x];
while(y!=p[y]&&++fy) y=p[y];
if(x==y)return ;
if(fx<fy)p[x]=y;
else p[y]=x;
}
、、、、、、、、、、、、、
# include <stdio.h> //用优先队列 时间开销小
# define N 1000001
void insert(int Tree[],int X);//向堆中插入值 S[WEI]
int Delmin(int Tree[]); //删除堆头-并返回堆头
int find(int x);
void Link(int x,int y);
int tree[N+1]; //堆
int p[N],Q[N],C[2*N];
int main(){
int i,j,k,l,m,n;
//freopen("DDD.txt","r",stdin);
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&j,&k);
if(!p[j])insert(tree,j);
if(!p[k])insert(tree,k);
if(find(j)!=find(k))
Link(j,k);
}
n=k=0;
while(tree[0])
Q[n++]=Delmin(tree);
for(i=m=k=0;i<n;i++)
if(p[Q[i]])
{
for(j=i,l=find(Q[i]);j<n;j++)
if(p[Q[j]]&&find(Q[j])==l)
{
C[k++]=Q[j];
printf("%d ",Q[j]);
}
while(m<k)p[C[m++]]=0;
k++;
printf("\n");
}
return 0;
}
void insert(int Tree[],int X)//向最小堆中插入X
{
int par,i=++Tree[0]; //插入X 后 Tree[0]+1
while(i>1) //直到i不是根节点
{
par=(i>>1); //父节点为par
if(Tree[par]<=X) break; //将<=改为>=即改为最大堆了
Tree[i]=Tree[par]; //否则调整堆 即位置上移
i=par;
}
Tree[i]=X; //插入新节点
}
int Delmin(int Tree[])
{
int i=1,L=2,root=Tree[1],X=Tree[Tree[0]--];
while(L<=Tree[0])
{
L+=L<Tree[0]&&Tree[L+1]<Tree[L];
if(Tree[L]>=X) break;
Tree[i]=Tree[L];
i=L; L=i<<1;
}
Tree[i]=X;
return root;
}
int find(int x)
{
if(!p[x]) p[x]=x;
while(x!=p[x])x=p[x];
return x;
}
void Link(int x,int y)
{
int fx=0,fy=0;
if(!p[x]) p[x]=x;
if(!p[y]) p[y]=y;
while(x!=p[x]&&++fx) x=p[x];
while(y!=p[y]&&++fy) y=p[y];
if(x==y)return ;
if(fx<fy)p[x]=y;
else p[y]=x;
}
--------------------------------
//
/*
EG:
15
1 99999999
3 2
5 2
8 5
9 6
7 6
4 10
10 6
88 4
88 99999999
2 99999999
8888 9999
9999 88888
777 88888
999 777
*/
#include<stdio.h>
#define N 100000000
# define max(a,b) (a)>(b)?(a):(b)
int p[N];
int Q[2*N],C[N];
int find(int x)
{
if(!p[x]) p[x]=x;
while(x!=p[x])x=p[x];
return x;
}
void Link(int x,int y)
{
int fx=0,fy=0;
if(!p[x]) p[x]=x;
if(!p[y]) p[y]=y;
while(x!=p[x]&&++fx)x=p[x];
while(y!=p[y]&&++fy)y=p[y];
if(x==y)return ;
if(fx<fy) p[x]=y;
else p[y]=x;
}
void change(int *a,int *b)//交换函数 交换a b的值
{
int c=*a;
*a=*b;
*b=c;
}
void Qsort(int A[],int L,int R)//快速排序 升序
{
int i=L,j=R,T=A[L]; //T为基准数
if(L>R) return;
while(i!=j) //当数组左右两边没相遇
{
while(A[j]>=T&&i<j)j--; //从右向左找 改为while(A[j]<=T&&i<j)
while(A[i]<=T&&i<j)i++; //从左向右找 改为while(A[i]>=T&&i<j) 这两处 改完即为降序
if(i<j)change(&A[i],&A[j]); //交换两数
}
if(L!=i)change(&A[L],&A[i]); //基准数归位
Qsort(A,L,i-1); //递归左
Qsort(A,i+1,R); //递归右
}
int main(){
int n,i,j,k,m;
//freopen("DDD.txt","r",stdin);
scanf("%d",&n);
for(i=0;i<n;i++)
{
j=i<<1;
scanf("%d%d",&Q[j],&Q[j+1]);
if(find(Q[j])!=find(Q[j+1]))
Link(Q[j],Q[j+1]);
}
n<<=1;
Qsort(Q,0,n-1);
for(i=j=k=0;j<n;i=j)
{
Q[k++]=Q[i];
while(j<n&&Q[i]==Q[++j]);
}//筛掉重复的值得到k个不同的值Q共k个
n=k;
for(i=m=k=0;i<n;i++)
if(p[Q[i]])
{
for(j=i;j<n;j++)
if(p[Q[j]]&&find(Q[i])==find(Q[j]))
C[k++]=Q[j];
while(m<k)p[C[m++]]=0;
k++;
}
for(i=0;i<k;i++)
{
if(C[i])printf("%d ",C[i]);
else printf("\n");
}
return 0;
}
//快排+筛选
______________________________________
/*
EG:
15
1 99999999
3 2
5 2
8 5
9 6
7 6
4 10
10 6
88 4
88 99999999
2 99999999
8888 9999
9999 88888
777 88888
999 777
*/
#include<stdio.h>
#define N 100000000
# define max(a,b) (a)>(b)?(a):(b)
int p[N],M,C[N];
int find(int x)
{
if(!p[x]) p[x]=x;
while(x!=p[x])x=p[x];
return x;
}
void Link(int x,int y)
{
int fx=0,fy=0;
if(!p[x]) p[x]=x;
if(!p[y]) p[y]=y;
while(x!=p[x]&&++fx)x=p[x];
while(y!=p[y]&&++fy)y=p[y];
if(x==y)return ;
if(fx<fy) p[x]=y;
else p[y]=x;
}
int main(){
int n,x,y,i,j,k,m;
//freopen("DDD.txt","r",stdin);
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
if(find(x)!=find(y))
Link(x,y);
M=max(M,max(x,y));
}
for(i=1,m=k=0;i<=M;i++)
{
if(p[i])
{
C[k++]=i;
for(j=1;j<=M;j++)
if(p[j]&&i!=j&&find(i)==find(j))
C[k++]=j;
while(m<k)p[C[m++]]=0;
k++;
}
}
for(i=0;i<k;i++)
{
if(C[i])printf("%d ",C[i]);
else printf("\n");
}
return 0;
}