2021-04-30 UVA10129 单词 Play on Words 欧拉回路

UVA10129 单词 Play on Words 欧拉回路的判断

题意翻译

输入n(n\leq100000)n(n≤100000)个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母可上一个单词的最后一个字母相同(例如acm,malform,mouseacm,malform,mouse)。每个单词最多包含10001000个小写字母。输入中可以有重复的单词。

输入输出样例

输入 #1复制

3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok

 欧拉道路:能否从无向图的一个结点出发走出一条道路,每条边恰好经过一次。这样的路线称为欧拉道路。

在一个联通的图中除了‘起点’‘终点’其余点的‘进’和‘出’(在有向图中分入度和出度)应该是相等的,也就是每个点的度都是偶数。

无向图中最多有两个点是奇点(度是奇数),有两个奇点则一定从一个奇点出发到另一个奇点结束。若都是偶点则可从任意点出发最后回到该点。

有向图中类似:最多只有两个点入读不等于出度。且互相差为1;从出度大1的点起始到入读大1的点结束。

该题可以把单词看作有向图,判断是否有欧拉道路,先判断是否联通,再判断度的关系是否满足;

#include<iostream>
#include<cstring>
#include<string>
using namespace std;
const int N = 27;
int m, n, x, y, p;
int in[N], ans[N], out[N], G[N][N], vis[N];
string c;
void dfs(int u)
{//判断图是否联通
	vis[u] = 0;//将该点标记为在图中;
	for (int v = 0; v < 26; ++v) {
		if (G[u][v]&&vis[v]) {//如果u,v,连接且v不在图中递归放到图中;
			dfs(v);
		}
	}
}
bool solve()
{
	cin >> n;
	memset(in, 0, sizeof(in));
	memset(out, 0, sizeof(out));
	memset(G, 0, sizeof(G));
	memset(vis, 0, sizeof(vis));
	for (int i = 0; i < n; ++i) {
		cin >> c;
		//scanf("%c",&c);
		x = c[0] - 'a', y = c.back() - 'a';
		G[x][y] = G[y][x] = 1;//因为欧拉回路是判断无向图是否连通
		vis[x] = vis[y] = 1;//标记出现的字母节点
		out[c[0] - 'a']++;
		in[c.back() - 'a']++;
	}
	dfs(x);
	bool  begin = false, end = false;
	for (int i = 0; i < 26; ++i) {
		if (vis[i])return false;//如果有字母存在且不再图中则不存在欧拉回路
		if (in[i] == out[i])continue;
		else {
			if (in[i] - out[i] == 1 && !end) {
				end = 1;
			}
			else if (out[i] - in[i] == 1 && !begin) {
				begin = 1;
			}
			else {
				return false;
			}
		}
	}
	return begin == end;
}
int main()
{
	cin >> m;
	while (m--)
	{
		if (solve()) {
			cout << "Ordering is possible.";
		}
		else cout << "The door cannot be opened.";
		cout << endl;
	}
	return 0;
}
#include<iostream>
#include<cstring>
#include<string>
#include<stack>
using namespace std;
const int N = 27;
int m, n, x, y, p, cnt;
int in[N], out[N], G[N][N], vis[N];
int map[N][N];
string c;
void dfs(int u)
{//判断图是否联通
	vis[u] = 0;//将该点标记为在图中;
	for (int v = 0; v < 26; ++v) {
		if (G[u][v]&&vis[v]) {//如果u,v,连接且v不在图中递归放到图中;
			dfs(v);
		}
	}
}
stack<int> ans;
void dfs2(int u) 
{//打印路径
	//cout << (char)(u+'a') << " ";
	ans.push(u); cnt--;
	for (int v = 0; v < 26&&cnt!=-1; ++v) {//寻找新的出发点
		if (map[v][u]) {
			map[v][u]--;
			dfs2(v);
			map[v][u]++;
		}
	}
	if (cnt == -1)return;
	cnt++;
	ans.pop();
}
bool solve()
{
	cin >> n;
	memset(in, 0, sizeof(in));
	memset(out, 0, sizeof(out));
	memset(G, 0, sizeof(G));
	memset(vis, 0, sizeof(vis));
	for (int i = 0; i < n; ++i) {
		cin >> c;
		cnt++;
		//scanf("%c",&c);
		x = c[0] - 'a', y = c.back() - 'a';
		G[x][y] = G[y][x] = 1;//因为欧拉回路是判断无向图是否连通
		map[x][y]++;
		vis[x] = vis[y] = 1;//标记出现的字母节点
		out[c[0] - 'a']++;
		in[c.back() - 'a']++;
	}
	dfs(x);
	bool  begin = false, end = false;
	for (int i = 0; i < 26; ++i) {
		if (vis[i])return false;//如果有字母存在且不再图中则不存在欧拉回路
		if (in[i] == out[i])continue;
		else {
			if (in[i] - out[i] == 1 && !end) {
				end = 1; y = i;
			}
			else if (out[i] - in[i] == 1 && !begin) {
				begin = 1; x = i;
			}
			else {
				return false;
			}
		}
	}
	return begin == end;
}
int main()
{
	cin >> m;
	while (m--)
	{
		cnt = 0;
		if (solve()) {
			dfs2(y);
			while (!ans.empty()) {
				cout << (char)(ans.top()+'a') << ' ';
				ans.pop();
			}
			cout << "Ordering is possible.";
		}
		else cout << "The door cannot be opened.";
		cout << endl;
	}
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值