集合归类

题目:对于集合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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值