Problem
给N个三元字符串Si,每个字符串只含有3个字符。现将N个字符串任意排序,使得对于i∈[1,N?1]满足Si[1..2]=Si+1[0..1]成立(比如:aba,bab,abc,bce)。问是否可以成立,若可以输出合并后的字符串(比如:aba,bab,abc,bce->ababce)
Limits
TimeLimit(ms):2000
MemoryLimit(MB):256
N∈[1,2×105]
字符集∈[a,z]?[A,Z]?[0,9]
Look up Original Problem From here
Solution
用有向图的欧拉路径来处理。
1. 建图:对于每个三元字符串Si,令hash1=Si[0..1],hash2=Si[1..2],将hash1->hash2连一条有向边,
2. 判断图G是否存在欧拉路径:
- G是一个联通图
- G中所有点入度=出度,或者,G中存在一个点入度-出度=1,一个点出度-入度=1,其余点入度=出度
3. 若存在,dfs求出答案
Complexity
TimeComplexity:O(N)
MemoryComplexity:O(N)
My Code
//Hello. I‘m Peter.
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<cctype>
#include<ctime>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double ld;
#define peter cout<<"i am peter"<<endl
#define input freopen("data.txt","r",stdin)
#define randin srand((unsigned int)time(NULL))
#define INT (0x3f3f3f3f)*2
#define LL (0x3f3f3f3f3f3f3f3f)*2
#define gsize(a) (int)a.size()
#define len(a) (int)strlen(a)
#define slen(s) (int)s.length()
#define pb(a) push_back(a)
#define clr(a) memset(a,0,sizeof(a))
#define clr_minus1(a) memset(a,-1,sizeof(a))
#define clr_INT(a) memset(a,INT,sizeof(a))
#define clr_true(a) memset(a,true,sizeof(a))
#define clr_false(a) memset(a,false,sizeof(a))
#define clr_queue(q) while(!q.empty()) q.pop()
#define clr_stack(s) while(!s.empty()) s.pop()
#define rep(i, a, b) for (int i = a; i < b; i++)
#define dep(i, a, b) for (int i = a; i > b; i--)
#define repin(i, a, b) for (int i = a; i <= b; i++)
#define depin(i, a, b) for (int i = a; i >= b; i--)
#define pi 3.1415926535898
#define eps 1e-6
#define MOD 1000000007
#define MAXN 5625
#define N
#define M
int idx(char c){
return c-‘0‘;
}
const int hashval=75;
int strhash(char c1,char c2){
return idx(c1)*hashval+idx(c2);
}
int n,maxi,origin;
queue<int>node[MAXN];
char s[10];
int indegree[MAXN],outdegree[MAXN];
string str[MAXN];
string make_string(char c1,char c2){
string res;
res.clear();
res+=c1,res+=c2;
return res;
}
void printno(){
printf("NO\n");
exit(0);
}
stack<int>st;
void dfs(int now){
while(!node[now].empty()){
int to=node[now].front();
node[now].pop();
dfs(to);
}
st.push(now);
}
bool vis[MAXN];
int main(){
scanf("%d",&n);
maxi=0;
origin=INT;
repin(i,1,n){
scanf("%s",s);
int v1=strhash(s[0],s[1]);
int v2=strhash(s[1],s[2]);
node[v1].push(v2);
maxi=max(maxi,v1),maxi=max(maxi,v2);
if(i==1) origin=v1;
outdegree[v1]+=1,indegree[v2]+=1;
if(!vis[v1]) str[v1]=make_string(s[0],s[1]),vis[v1]=true;
if(!vis[v2]) str[v2]=make_string(s[1],s[2]),vis[v2]=true;
}
int num01=0,num10=0,numodd=0;
repin(i,0,maxi){
if(indegree[i]!=outdegree[i]){
numodd+=1;
if(indegree[i]-outdegree[i]==1) num10+=1;
else if(outdegree[i]-indegree[i]==1) num01+=1,origin=i;
else printno();
}
}
if(numodd!=0 && numodd!=2) printno();
else if(numodd==2 && (num10!=1 || num01!=1)) printno();
dfs(origin);
repin(i,0,maxi){//判断图是否整体连通,这一步容易被忽略..
if(!node[i].empty()) printno();
}
printf("YES\n");
string ans;
while(!st.empty()){
int now=st.top();
st.pop();
ans+=str[now][0];
if(st.empty()) ans+=str[now][1];
}
cout<<ans<<endl;
}
时间: 2024-11-04 20:05:18