P1341 无向图的欧拉路径
无序字母对
题目描述
给定 \(n\) 个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有 \((n+1)\) 个字母的字符串使得每个字母对都在这个字符串中出现。
输入格式
第一行输入一个正整数 \(n\)。
第二行到第 \((n+1)\) 行每行两个字母,表示这两个字母需要相邻。
输出格式
输出满足要求的字符串。
如果没有满足要求的字符串,请输出 No Solution
。
如果有多种方案,请输出字典序最小的方案(即满足前面的字母的 ASCII 编码尽可能小)。
样例 #1
样例输入 #1
4
aZ
tZ
Xt
aX
样例输出 #1
XaZtX
提示
不同的无序字母对个数有限,\(n\) 的规模可以通过计算得到。
注意无向图没有 in out 统一为 deg
欧拉回路 : 所有点度数相同
欧拉路径 : 奇数度的点数恰好为2
用并查集判断是否联通
由于这要求n+1个且为字母对 而且N范围很小 所以在 dfs 中用vis数组 同时要将 vis[x][i] vis[i][x]都置为0!
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e3+5;
int deg[N],stack_[N],pt,n;
vector<int>G[N];
int fa[N];
int cur[N];
int vis[N][N];
int getfa(int x) {
if(fa[x]==x)return x;
return fa[x]=getfa(fa[x]);
}
void dfs(int u) {
for(int i=1; i<=125; i++) {
if(vis[u][i]) {
vis[u][i]=vis[i][u]=0;
dfs(i);
}
}
stack_[++pt]=u;
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<=125; i++)fa[i]=i;
for(int i=1; i<=n; i++) {
string s;
cin>>s;
G[s[0]].push_back(s[1]);
G[s[1]].push_back(s[0]);
vis[s[0]][s[1]]=vis[s[1]][s[0]]=1;
deg[s[0]]++;
deg[s[1]]++;
int fx=getfa(s[0]),fy=getfa(s[1]);
fa[fx]=fy;
}
int root_cnt=0;
for(int i=1; i<=125; i++)
if(deg[i]&&fa[i]==i)
root_cnt++;
if(root_cnt!=1) {
cout<<"No Solution\n";
return 0;
}
for(int i=1; i<=n; i++)sort(G[i].begin(),G[i].end());
int start=-1,odd_cnt=0;
for(int i=1; i<=125; i++)
if(deg[i]&1) {
odd_cnt++;
if(start==-1)start=i;
}
if(odd_cnt&&odd_cnt!=2) {
cout<<"No Solution\n";
return 0;
}
if(start==-1)//loop
for(int i=1; i<=125; i++)
if(deg[i]) {
start=i;
break;
}
dfs(start);
while(pt) {
cout<<char(stack_[pt]);
pt--;
}
return 0;
}