题目描述:
给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。
输入:
第一行输入一个正整数n。
以下n行每行两个字母,表示这两个字母需要相邻。
输出:
输出满足要求的字符串。
如果没有满足要求的字符串,请输出“No Solution”。
如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案
算法标签:欧拉路??我觉得我是贪心爆搜啊??
写完才知道欧拉路是个什么鬼
思路:
有两种情况,第一种存在两个度数为奇数的点,此时在两个点内挑一个字典序小的暴力跑,每次优先跑字典序小的,跑到底不合法return,换路跑,暴力的很。
第二种情况所有点度数为偶数,此时要合法说明是一个欧拉回路,所以选一个字典序最小的跑。
以下代码:
#include<bits/stdc++.h> #define il inline #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=55,M=3005; int n,in[N],que[55],tot,fir,kk,link[N][N],res[M],tt; char s[10]; il int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=(x<<1)+(x<<3)+(ch^48);return f*x;} il int getnum(char t){ if(t>='A'&&t<='Z')return t-'A'+1;return t-'a'+27; } il char getch(char t){ if(t<=26)return t+'A'-1;return t+'a'-27; } il bool work(int x,int tt){ res[tt]=x;if(tt==n+1)return 1; for(int i=1;i<=52;i++){ if(link[x][i]){ link[x][i]=0;link[i][x]=0;if(work(i,tt+1))return 1; link[x][i]=1;link[i][x]=1; } } return 0; } int main() { n=read();for(int i=1;i<=n;i++){ scanf(" %s",&s);int x=getnum(s[0]),y=getnum(s[1]); link[x][y]=link[y][x]=1;in[x]++;in[y]++; } for(int i=1;i<=52;i++){ if(in[i]&1)que[++tot]=i;if(!fir&&in[i])fir=i; } if(tot>2){puts("No Solution");return 0;} if(tot==2){if(que[1]<que[2])fir=que[1];else fir=que[2];} int x=fir; if(!work(fir,1)){puts("No Solution");return 0;} for(int i=1;i<=n+1;i++)printf("%c",getch(res[i])); return 0; }