给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现……
一 题目
原题链接
描述
给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。
输入
第一行输入一个正整数n。
以下n行每行两个字母,表示这两个字母需要相邻。
输出
输出满足要求的字符串。
如果没有满足要求的字符串,请输出“No Solution”。
如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案。
二 题解
把单个字母看作图上的点,字母的相邻关系(也就是上文中的“字母对”)看作无向边。即对于一个字母对$ab$,将$a$与$b$连无向边。
题目中描述“使得每个字母对都在这个字符串中出现”,即可看作图上的每条边都要被经过。所以得出本题为欧拉路问题,求出字典序最小的欧拉道路(或回路)即可解决问题。
因为一共26个英文字母,算上大小写区分还不到100个,所以本题使用邻接矩阵存图更为方便。直接把char型字符强制转换为int型的ascii码,求解即可。
注意:在涉及类型转换时,需要注重细节的处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> using namespace std;
const int CP=1e3+3; const int CE=CP*CP;
bool g[CP][CP];
int elm[CP]; bool ap[CP];
int n;
int deg[CP]; int list[CP];
bool exm(){ int sum=0; for(int i=1;i<=n;i++) if(deg[elm[i]]%2) sum++; return sum<=2; } void dfs(int u) { for(int j=1;j<=elm[0];j++) { int v=elm[j]; if(g[u][v]) { g[u][v]=g[v][u]=false; dfs(v); } } list[++list[0]]=u; }
int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { char _x,_y; cin>>_x>>_y; int x=_x,y=_y; g[x][y]=g[y][x]=true; deg[x]++; deg[y]++; if(!ap[x]) { elm[++elm[0]]=x; ap[x]=true; } if(!ap[y]) { elm[++elm[0]]=y; ap[y]=true; } } sort(elm+1,elm+elm[0]+1); int s=elm[1]; for(int i=1;i<=n&&s==elm[1];i++) if(deg[elm[i]]%2) s=elm[i]; dfs(s); if(exm() && list[0]==n+1) for(int i=list[0];i;i--) { char c=list[i]; cout<<c; } else printf("No Solution"); return 0; }
|