题意:
给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。
解法:
一道欧拉回路的模板题。将每个字母两两之间连一条无向边,然后求欧拉回路(保证字典序最小)。
#include<iostream>
#include<stack>
#define N 60
#define tint(_) (int(_-'A'))
#define tchar(_) (char(_+'A'))
using namespace std;
bool e[N][N]={0};
int n,d[N],f[N],s;
stack<int> st;
void out();
void dfs(int x);
void finds();
int fnd(int x);
void uni(int x,int y);
bool check();
void init();
int main()
{
init();
if(check())
{
cout<<"No Solution";
return 0;
}
finds();
dfs(s);
out();
return 0;
}
void out()
{
while(!st.empty())
{
cout<<tchar(st.top());
st.pop();
}
}
void init()
{
cin>>n;
for(int i=0;i<=N;i++)
f[i]=i;
for(int i=1;i<=n;i++)
{
char zu,zv;
int u,v;
cin>>zu>>zv;
u=tint(zu); v=tint(zv);
d[u]++; d[v]++;
uni(u,v);
e[u][v]=1;
e[v][u]=1;
}
}
bool check()
{
int j=0,now=0,fa;
for(int i=0;i<=N;i++)
if(d[i]%2==1)
j++;
if(j&&j!=2)
return 1;
while(!d[now++]);
now--;
fa=fnd(now);
for(int i=now+1;i<=N;i++)
if(d[i]&&fnd(i)!=fa)
return 1;
return 0;
}
int fnd(int x)
{
if(f[x]==x)
return x;
return f[x]=fnd(f[x]);
}
void uni(int x,int y)
{
if(fnd(x)!=fnd(y))
f[fnd(x)]=fnd(y);
}
void finds()
{
s=0;
for(int i=0;i<=N;i++)
if(d[i]%2==1)
{
s=i;
break;
}
if(n==1)
s=0;
if(!s)
for(int i=0;i<=N;i++)
if(d[i])
{
s=i;
return;
}
}
void dfs(int x)
{
for(int i=0;i<=N;i++)
if(e[x][i])
{
e[x][i]=0;
e[i][x]=0;
dfs(i);
}
st.push(x);
}