题目描述
给定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;
}