P1341 无序字母对 (欧拉回路)

题目描述

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

输入输出格式

输入格式:

 

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

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

 

输出格式:

 

输出满足要求的字符串。

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

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

 

输入输出样例

输入样例#1:
4
aZ
tZ
Xt
aX
输出样例#1: 
XaZtX
 

说明

【数据规模与约定】

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

 

虽然题面看起来像是字符串的题,但是实际上只是一个简单的欧拉回路.

这里在边这里很容易走进一个误区,也就是把每个字母对作为单独的一个点,虽然可以,但实际操作起来却会发现很棘手,所以不要把每个字母对作为点,然后再去连边.因为每个字母对都是正反皆可.所以这样还要考虑到每个字母对的反转问题.然后就变成了一个超级麻烦的东西.

首先要想到把字母化成点,然后由于每次输入的是字母对,所以可以每两个字母直接连一条边,每个单一的字母看成一个集合,也就是都看成一个点.这里可以用一个vector来减小内存.然后,就是欧拉回路的性质可以来快速判断有无回路.也就是如果一个无向图的每个节点的度都为偶数,或者只有两个点的度是奇数的话(起点终点).然后每个字母变成一个点之后,然后就是DFS即可.

菜狗呈上代码:

 

#include<algoirthm> 
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<stack>
#include<queue>
#include<map>
#include<set> using namespace std; const int maxn=5005; int n; char s[5]; struct node{ int x; int idx; }; vector<node>g[60]; vector<int>eg; int du[60],vis[maxn]; int vis1[60];
bool cmp(node kkk,node ttt) { return kkk.x<ttt.x; }
inline
void dfs(int i) { for(int k=0;k<g[i].size();k++) { int j=g[i][k].x,id=g[i][k].idx; if(vis[id]) continue; vis[id]=1; dfs(j); } eg.push_back(i); }
inline
void read(int i) { scanf("%s",s); int a=s[0]-'A'+1; int b=s[1]-'A'+1; g[a].push_back((node){b,i}); g[b].push_back((node){a,i}); du[a]++; du[b]++; vis1[a]=1; vis1[b]=1; }
int main() { scanf("%d",&n); memset(du,0,sizeof(du)); memset(vis1,0,sizeof(vis1)); for(int i=1;i<=n;i++) read(i); for(int i=1;i<60;i++) sort(g[i].begin(),g[i].end(),cmp); int s,cnt=0,pd=1; for(int i=1;i<60;i++) if(du[i]%2==1) cnt++; if(cnt!=2 && cnt!=0) pd=0; if(pd==0) { cout<<"No Solution"<<endl; return 0; } int ks; for(int i=1;i<60;i++) if(vis1[i]==1) { ks=i; break; } for(int i=1;i<60;i++) if(du[i]%2==1) { ks=i; break; } memset(vis,0,sizeof(vis)); dfs(ks); for(int i=eg.size()-1;i>=0;i--) printf("%c",eg[i]-1+'A'); return 0; }

 

posted @ 2018-01-15 00:58  Kevin_naticl  阅读(331)  评论(0编辑  收藏  举报