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;
}
posted @ 2023-04-23 20:38  N0zoM1z0  阅读(9)  评论(0编辑  收藏  举报