UVA-10129-Play-on-Words-欧拉路径-半欧拉图

文章讲述了如何通过构造一个有向图并应用欧拉路径理论来判断给定一组单词能否形成一个满足首尾字母相连的序列。关键步骤包括计算结点的入度和出度,检查奇点数量,以及利用深度优先搜索验证连通性。

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

题目大意原题链接

        给若干个单词,判断是否可以把所有单词排成一个序列,序列中每个单词的最后字母与下一个单词的第一个字母相同。例:ACM-MAC-CBA。

de449de6-c455-4619-b317-b84890877ee4

理论基础

        欧拉路径: 从图中的一个结点出发走出的一条路径,而且图中的每条边恰好经过一次。

        欧拉回路:指起点和终点相同的欧拉路径。

        半欧拉图:具有欧拉路径但不具有欧拉回路的图。

        存在条件:①忽略边的方向后图是连通的;②对于无向图:有2个或0个奇点(结点度数为奇数);对于有向图:有2个或0个奇点(一个出度必须比入度大1,另一个入度必须比出度大1,分别作为起点和终点)。

解题思路

         可将单词的第一个和最后一个字母当成结点,单词看成有向边,所有单词构成一个有向图。若图中存在欧拉路径则问题有解,判断欧拉路径的存在条件是否成立即可。详见代码。

参考代码 

#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
#define maxn 26

void dfs(int node, int *vis, int G[][maxn]) {
	vis[node] = 1;
	for (int i = 0; i < maxn; i++)
		if (G[node][i] && !vis[i])
			dfs(i, vis, G);
}

int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		int in[maxn] = {0}, out[maxn] = {0}, G[maxn][maxn] = {0}, vis[maxn] = {0};
		int num1 = 0, num2 = 0, pass = 1, n;
		//in、out分别记录结点入度和出度,num1记录入度大1结点个数,num2记录出度大1结点个数
		scanf("%d", &n);
		while (n--) {
			string s;
			cin >> s;
			out[s[0] - 'a']++;	//统计结点入度和出度
			in[s[s.size() - 1] - 'a']++;
			G[s[0] - 'a'][s[s.size() - 1] - 'a'] = 1;
		}

		for (int i = 0; i < maxn; i++) {	//统计寄点个数
			if (in[i] != out[i]) {
				if (in[i] == out[i] + 1)
					num1++;
				else if (out[i] == in[i] + 1)
					num2++;
				else {	//入、出度不符合要求
					pass = 0;
					break;
				}
			}
		}
		if (num1 + num2 > 2) pass = 0;	//奇点个数不符合要求
		if (pass) {
			for (int i = 0; i < maxn; i++)	//使用dfs判断图是否连通
				if (out[i]) {
					dfs(i, vis, G);
					break;
				}
			for (int i = 0; i < maxn; i++)	//若每个结点都被访问,则连通,否则不连通
				if (out[i] + in[i] > 0 && !vis[i]) {
					pass = 0;
					break;
				}
			if (pass)
				puts("Ordering is possible.");
			else
				puts("The door cannot be opened.");
		} else
			puts("The door cannot be opened.");
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

✷大傻瓜✷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值