题意:
n(10^5)个串每个串3个字符 两个串abc、xyz能拼在一起前提是b=x&&c=y 它们能拼成ab(x)c(y)z 求n个串品在一起的串
思路:
将串abc变成ab->bc的一条边 则原题变成了有向图的欧拉路径问题
有向图欧拉路径算法就是遍历 因为欧拉路径其实就是“每条边走一遍”
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef unsigned long long ULL;
#define N 3850
int n,m;
int in[N],out[N],Edge[N][N],ans[200010];
int get(char a){
if(a>='0'&&a<='9') return a-'0';
if(a>='A'&&a<='Z') return a-'A'+10;
return a-'a'+36;
}
char put(int a){
if(a>=0&&a<=9) return '0'+a;
if(a>=10&&a<=35) return 'A'+a-10;
return 'a'+a-36;
}
void dfs(int x){
for(int i=0;i<N;i++){
while(Edge[x][i]){
Edge[x][i]--;
dfs(i);
ans[m++]=i;
}
}
}
int main(){
char s[10];
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",s);
int u=get(s[0])*62+get(s[1]);
int v=get(s[1])*62+get(s[2]);
in[v]++;
out[u]++;
Edge[u][v]++;
}
int can=1,st=-1,ed=-1;
for(int i=0;i<N;i++){
int tmp=in[i]-out[i];
if(abs(tmp)>1){
can=0;
break;
}else if(tmp==1){
if(ed==-1) ed=i;
else{
can=0;
break;
}
}else if(tmp==-1){
if(st==-1) st=i;
else{
can=0;
break;
}
}
}
if(can){
if(st==-1){
for(int i=0;i<N;i++) if(out[i]){
st=i;
break;
}
}
dfs(st);
ans[m++]=st;
if(m==n+1){
puts("YES");
for(int i=m-1;i>=0;i--){
if(i!=m-1) printf("%c",put(ans[i]%62));
else printf("%c%c",put(ans[i]/62),put(ans[i]%62));
}
puts("");
}else puts("NO");
}
else puts("NO");
return 0;
}