Uva10129——Play on Words

本文介绍了一种通过将问题转化为有向图的欧拉回路判断来解决特定问题的方法,并使用并查集确保图的连通性。代码实现了节点的入度与出度计算、并查集的查找与合并操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题,可以转换成有向图的欧拉回路的判断。

有向图的判断方法:所以点的入度等于出度或者有一个点的出度比入度大1有一个点的入度比出度大1,剩下的点入度等于出度。

不过还有一个前提,就是图是连通的,可以用DFS来判断或者并查集。我用的是并查集。


代码:

#include <iostream>
#include <cstring>
using namespace std;

struct node
{
	int indegree, outdegree;
};

int pre[30], flag[30];

node degree[30];

bool ans;

int finds(int x)            //并查集查找函数
{
	int r = x;
	while(pre[r] != r)
		r = pre[r];

	int i = x, j;
	while(i != r)
	{
		j = pre[i];
		pre[i] = r;
		i = j;
	}
	return r;
}

void join(int x, int y)  //并查集合并函数
{
	int fx = finds(x);
	int fy = finds(y);
	if(fx != fy)
		pre[fx] = fy;
}

int main()
{
//	freopen("1.txt", "r", stdin);
	int t, n, len, i;
	char str[1005];
	cin >> t;
	while(t--)
	{
		cin >> n;
		ans = false;
		for(i = 0; i < 30; i++)
		{
			pre[i] = i;
			degree[i].indegree = degree[i].outdegree = 0;
		}
		memset(flag, 0, sizeof(flag));
		while(n--)
		{
			cin >> str;
			len = strlen(str);
			flag[str[0] - 'a'] = flag[str[len - 1] - 'a'] = 1;
			join(str[0] - 'a', str[len - 1] - 'a');
			degree[str[0] - 'a'].outdegree++;
			degree[str[len - 1] - 'a'].indegree++;
		}
		i = 0;                            //判断图是否连通
		while(flag[i] == 0) i++;
		int par = finds(i);
		for( ; i < 26; i++)
			if(flag[i] && finds(i) != par)
			{
				ans = true;
				break;
			}
		if(ans)
			cout << "The door cannot be opened." << endl;
		else       //判断是否存在欧拉回路
		{
			int a, b, c, count;
			a = b = c = count = 0;
			for(i = 0; i < 26; i++)
			{
				if(flag[i])
				{
					count++;
					if(degree[i].indegree - degree[i].outdegree == 1)
						a++;
					else if(degree[i].indegree - degree[i].outdegree == -1)
						b++;
					else if(degree[i].outdegree == degree[i].indegree)
						c++;
				}
			}
			if((a == 1 && a == b && c == count - 2) || (a == 0 && a == b && c == count))
				cout << "Ordering is possible." << endl;
			else
				cout << "The door cannot be opened." << endl;
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值