【数据结构】并查集之二

前端之家收集整理的这篇文章主要介绍了【数据结构】并查集之二前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1. 两类类别


并查集中有两类类别,即并查集中元素要么属于集合A,要么属于B,且A与B不相交。

利用向量得到关系:



1.1 POJ 2492


代码:

#include "stdio.h"

int parent[2000],relation[2000];

int find(int x)   
{
	int root,tail,temp;
	if(parent[x]==x)
		return x;	
    else
	{
		for(root=x;parent[root]!=root;root=parent[root]);
		
		for(tail=x;tail!=root;)
		{
			temp=parent[tail];
			parent[tail]=root;
			tail=temp;
		}
		return root;
	}
	
}

void update(int yroot,int n)
{
	int i;
	for(i=1;i<=n;i++)
	{
		if(i!=yroot&&find(i)==yroot)
			relation[i]=(relation[i]+relation[yroot])%2;
	}
}

void root_union(int x,int y,int xroot,int yroot,int n)
{
	relation[yroot]=(relation[x]-relation[y]+1)%2;
	update(yroot,n);
	parent[yroot]=xroot;
}


int main()
{
	int scena_num,bug_num,intera_num,a,b,i,count;
	int aroot,broot,suspi_flag;
    scanf("%d",&scena_num);
	for(count=1;count<=scena_num;count++)
	{
		scanf("%d%d",&bug_num,&intera_num);
		suspi_flag=0;
		for(i=1;i<=bug_num;i++)
		{
			parent[i]=i;
			relation[i]=0;
		}
		while(intera_num--)
		{
			scanf("%d%d",&a,&b);
			aroot=find(a);
			broot=find(b);
			
			if(aroot!=broot)
			{
				root_union(a,aroot,bug_num);
			}
			else
			{
				if(relation[a]!=(relation[b]+1)%2)   
					suspi_flag=1;					
			}			
		}
		if(suspi_flag==1)
			printf("Scenario #%d:\nSuspicIoUs bugs found!\n\n",count);
		else
			printf("Scenario #%d:\nNo suspicIoUs bugs found!\n\n",count);
		
	}
	return 0;
}

1.2 POJ 1703


代码:

#include "stdio.h"

int parent[100000],relation[100000];

int find(int x)   //寻找root结点,并更新parent链域的relation值
{
	int temp;
	if(parent[x]==x)
		return x;	
    
	temp=parent[x];
	parent[x]=find(parent[x]);
	relation[x]=(relation[x]+relation[temp])%2;   	    
	return parent[x];
}

int main()
{
	int T,N,M,b;
	int aroot,broot;
	char message;
    scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&N,&M);
		for(i=1;i<=N;i++)
		{
			parent[i]=i;
			relation[i]=0;
		}
		while(M--)
		{
			getchar();
			scanf("%c%d%d",&message,&b);
			aroot=find(a);
			broot=find(b);
			if(message=='A')
			{
				if(N==2&&a!=b)
					printf("In different gangs.\n");
				else
				{
					if(aroot==broot)
					{
						if(relation[a]==relation[b])
							printf("In the same gang.\n");
						else
							printf("In different gangs.\n");
					}
					else
						printf("Not sure yet.\n");
				}
			}
			else
			{
				if(aroot!=broot)
				{
					parent[broot]=aroot;
					relation[broot]=(relation[a]-relation[b]+1)%2;
				}
			}
		}
	}
	return 0;
}


2. 三类类别


并查集中元素属于互不相交的集合A,B,C。


类似地,可以得到如下关系:

r[y]=(r[x]+d)%3 //不能得到r[x]=(r[y]+d)%3

r[yroot]=(r[x]-r[y]+d+3)%3 //+3,是因为r[x]-r[y]+d有可能为负数

其中,0表示与root节点同类,1表示吃root节点,2表示被root节点吃。


2.1POJ 1182


代码:

#include "stdio.h"

int parent[50000],relation[50000];

int find(int x)   
{
	int temp;
	if(parent[x]==x)
		return x;	
    
	temp=parent[x];
	parent[x]=find(parent[x]);
	relation[x]=(relation[x]+relation[temp])%3;   	    
	return parent[x];
}

int main()
{
	int num_ani,num_sta,statement,count=0;
	int a,d;
    scanf("%d%d",&num_ani,&num_sta);
	for(i=1;i<=num_ani;i++)
	{
		parent[i]=i;
		relation[i]=0;
	}
	while(num_sta--)
	{
		getchar();
		scanf("%d%d%d",&statement,&b);
		d=statement-1;
        if(a>num_ani||b>num_ani)
			count++;
		else
		{
			aroot=find(a);
			broot=find(b);
			if(aroot!=broot)
			{
				parent[broot]=aroot;
				relation[broot]=(relation[a]-relation[b]+d+3)%3;
			}
			else if(relation[b]!=(relation[a]+d)%3||(d==1&&a==b))
				count++;
		}
	}
	printf("%d\n",count);
	return 0;
}

猜你在找的数据结构相关文章