P1341 无序字母对 - 欧拉回路的判断和输出路径

题目描述

给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。

输入格式

第一行输入一个正整数n。

以下n行每行两个字母,表示这两个字母需要相邻。

输出格式

输出满足要求的字符串。

如果没有满足要求的字符串,请输出“No Solution”。

如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案

输入输出样例

输入 #1复制

4
aZ
tZ
Xt
aX

输出 #1复制

XaZtX
 

说明/提示

【数据规模与约定】

不同的无序字母对个数有限,n的规模可以通过计算得到。

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 1e4+4;
int A[maxn][maxn];//存图
vector<int>cu(maxn);//存出度
char ans[maxn];//存答案
int n; 
int f[maxn];    //并查集数组                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
void add(int x, int y) {
	A[x][y] = 1;
	A[y][x] = 1;
}//加边
int find(int x) {
	if(x == f[x]) {
		return f[x];
	}
	else {
		return f[x] = find(f[x]);
	}
}//并查集查询father
int dfs(int x) {
	for(int i = 0;i <= 'z'-'A';++i) {
		if(A[x][i]) {
			A[x][i] = 0;
			A[i][x] = 0;
			dfs(i);
		}
	}
	ans[n--] = x + 'A';
}//dfs搜索路径并存到ans中
int main() {
	scanf("%d", &n);
	for(int i = 0;i <= 200;++i) {
		f[i] = i;
	}//并查集初始化
	for(int i = 1;i <= n;++i) {
		char a[3];
		cin >> a;
		int x = a[0] - 'A';
		int y = a[1] - 'A';
		cu[x]++;
		cu[y]++;//加入度便于查找头和判断是否是欧拉图
		add(x, y);//加边
		x = find(x);
		y = find(y);
		if(x != y) {
			f[x] = y;	
		}//并查集
	}
	int sum = 0;
	for(int i = 0;i <= 'z'-'A';++i) {
		if(find(i) == i && cu[i]) {
			sum++; 
		}
	}//判断有入度的并且是联通快的是几个
	if(sum != 1) {
		printf("No Solution\n");return 0;
	} //不是一个联通快输出no
	int head = -1;
	int cnt = 0;
	for(int i = 0;i <= 'z'-'A';++i) {
		if(cu[i]&1) {
			cnt++;
			if(head == -1) {
				head = i;
			}
		}
	}//查找头部按字典序
	if(head == -1) {
		for(int i = 0;i < 'z'-'A';++i) {
			if(cu[i]) {
				head = i;break;
			}
		}
	}//头部没有就看看成环的字典序最小的
	if(cnt && cnt != 2) {
		printf("No Solution\n");return 0;
	}//有头的且头不是2个一个结尾一个开始的输出no
	dfs(head);//从头开始找
	cout << ans << '\n';//输出答案
	return 0;
}
发布了219 篇原创文章 · 获赞 43 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/qq_43568078/article/details/103391281
今日推荐