2013寒假练习 1063 食物链(另1062 Find them, Catch them,1061 Ubiquitous Religions)

地址:http://acm.bit.edu.cn/mod/programming/view.php?a=549

经典拓展(真)并查集,多码几次没坏处。

难点:merge时,relation的变更容易搞混。原理是b对a的关系等于b对c+c对a的关系(注意有先后)。故merge时已知a对roota关系temp1.r,b对roota关系temp2.r,a对b关系s,则roota对rootb关系为 -temp1.r+s+temp2.r  然后+3再%3(防止负数取余)

WA点:注意不要出现负数取余。

#include<iostream>
#define N 50005
int parent[N],relation[N];  //2表示被吃,1表示吃,0表示同类
typedef struct NODE
{
	int p,r;
}node;
node ans,temp1,temp2;
node root(int a)
{
	if(parent[a]==-1)
	{
		ans.p=a,ans.r=0;
		return ans;
	}
	ans=root(parent[a]);
	ans.r=relation[a]=(ans.r+relation[a])%3;  //路径压缩优化
	parent[a]=ans.p;
	return ans;
}
void merge(int s,int a,int b)
{
	node roota=root(a),rootb=root(b);
	parent[roota.p]=rootb.p;
	relation[roota.p]=(rootb.r-roota.r+s+3)%3;
}
int main()
{
	int n,k;
	int cmd,t1,t2;
	int res;
	while(~scanf("%d%d",&n,&k))
	{
		memset(relation,0,sizeof(relation));
		memset(parent,-1,sizeof(parent));
		res=0;
		while(k--)
		{
			scanf("%d%d%d",&cmd,&t1,&t2);
			if(t1>n||t2>n||(t1==t2&&cmd==2))    
			{
				res++;
				continue;
			}
			temp1=root(t1),temp2=root(t2);
			if(cmd==1)
			{
				if(temp1.p==temp2.p)
				{
					if(temp1.r==temp2.r) 	continue;
					else
					{
						res++;
						continue;
					}
				}
				else merge(0,t1,t2);
			}
			else
			{
				if(temp1.p==temp2.p)
				{
					if((temp1.r-temp2.r+3)%3==1)  continue;
					else
					{
						res++;
						continue;
					}
				}
				else merge(1,t1,t2);
			}
		}
		printf("%d\n",res);
	}
	return 0;
}

 1062 Find them, Catch them

地址:http://acm.bit.edu.cn/mod/programming/view.php?a=548

弱化版。

#include<iostream>
using namespace std;
#define SIZE 100005
int parent[SIZE],relation[SIZE];
struct NODE
{
	int p,r;
} temp1,temp2,ans;
struct NODE root(int n)
{
	if(parent[n]==-1) 
	{
		ans.p=n,ans.r=0;
		return ans;
	}
	ans=root(parent[n]);
	parent[n]=ans.p;                            //路径压缩
	ans.r=relation[n]=(relation[n]+ans.r)%2;
	return ans;
}
void merge(int a,int b)
{
	temp1=root(a),temp2=root(b);
	if(temp1.p==temp2.p) return;
	parent[temp1.p]=temp2.p;
	relation[temp1.p]=(temp1.r+temp2.r+1)%2;
}
int main()
{
	int t,m,n,t1,t2;
	char cmd;
	scanf("%d",&t);
	while(t--)
	{
		memset(parent,-1,sizeof(parent));
		memset(relation,0,sizeof(relation));
		scanf("%d%d%*c",&n,&m);
		while(m--)
		{
			scanf("%c%d%d%*c",&cmd,&t1,&t2);
			if(cmd=='D') merge(t1,t2);
			else
			{
				temp1=root(t1),temp2=root(t2);
				if(temp1.p!=temp2.p) printf("Not sure yet.\n");
				else
				{
					if(temp1.r==temp2.r) printf("In the same gang.\n");
					else printf("In different gangs.\n");
				}	
			}
		}
	}
	return 0;
}

1061 Ubiquitous Religions

地址:http://acm.bit.edu.cn/mod/programming/view.php?a=547

基础并查集。

#include<iostream>
using namespace std;
int father[50005];
bool flag[50005];
int m,n,t1,t2;
int root(int n)
{
	if(father[n]<0) return n;
	else return father[n]=root(father[n]);
}
void merge(int a,int b)
{
	int roota=root(a),rootb=root(b);
	if(father[roota]>father[rootb]) father[rootb]+=father[roota],father[roota]=rootb;
	else father[roota]+=father[rootb],father[rootb]=roota;
}
int main()
{
	int case0=1;
	while(scanf("%d%d",&n,&m),m||n)
	{
		int ans=0;
		memset(father,-1,sizeof(father));
		memset(flag,0,sizeof(flag));
		while(m--)
		{
			scanf("%d%d",&t1,&t2);
			if(root(t1)!=root(t2)) merge(t1,t2);
		}
		for(int i=1;i<=n;i++)
		{
			if(!flag[root(i)]) ans++,flag[root(i)]=1;
		}
		printf("Case %d: %d\n",case0++,ans);
	}
	return 0;
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值