题意:

给定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);
}
02-12 13:32