HDU-3926 Hand in Hand(图的同构+并查集水题)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3926

题意:T组样例。每个样例给出两个图。每个图的所有点最大度数为2,问两个图是否同构。

思路:由于点的最大度为2,那么图可能会分为若干个连通块,并且要么是一个圆要么是一条线,显然用并查集记下每个练通块的大小以及是圆是线,排序后判断一下即可。

PS:以为是个图同构的题,没想到是道并查集水题。以后还是不用结构体封装了,作用不大。。。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4+10; 
int u,v;
struct node
{
	int num;
	bool yuan;
};
struct Union_Find
{
	int fa[N],n,m,fu,fv;
	struct node a[N];
	void Init()
	{
		for(int i=1;i<=n;i++)
			a[i].yuan=0,a[i].num=1,fa[i]=i;
		return ;
	}
	int Getf(int x)
	{
		return fa[x]==x?x:fa[x]=Getf(fa[x]);
	}
	void Merge(int u,int v)
	{
		fu=Getf(u); fv=Getf(v);
		if(fu!=fv) 
		{
			fa[fu]=fv;
			a[fv].num+=a[fu].num;
			a[fu].num=0;
		}
		else
			a[fv].yuan=1;
		return ;
	}		
}g1,g2;

bool Cmp(const node& a,const node& b)
{
	if(a.num==b.num)
		return a.yuan>b.yuan;
	else return a.num>b.num;	
}	
int main(void)
{
	int t,tt=0;
	bool no;
	scanf("%d",&t);
	while(t--)
	{
		no=0;
		scanf("%d%d",&g1.n,&g1.m);
		g1.Init();
		for(int i=1;i<=g1.m;i++)
		{
			scanf("%d%d",&u,&v);
			g1.Merge(u,v);		
		}
		scanf("%d%d",&g2.n,&g2.m);
		if(g2.n!=g1.n||g2.m!=g1.m)
		{
			no=1;
		}
		if(!no)
			g2.Init();
		for(int i=1;i<=g2.m;i++)
		{
			scanf("%d%d",&u,&v);
			if(no) continue;
			g2.Merge(u,v);		
		}
		printf("Case #%d: ",++tt);
		if(no)
		{
			printf("NO\n");
			continue;
		}
		sort(g1.a+1,g1.a+g1.n+1,Cmp);
		sort(g2.a+1,g2.a+g2.n+1,Cmp);
		for(int i=1;i<=g1.n;i++)
		{			
			if(g1.a[i].num!=g2.a[i].num||g1.a[i].yuan!=g2.a[i].yuan)	
			{
				no=1;
				break;
			}
		}
		printf(no?"NO\n":"YES\n");
	}
	
	return 0;	
} 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值