题意:
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; }
时间: 2024-10-05 03:31:14