洛谷1341 无序字母对(欧拉路)

【问题描述】

  给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒)。请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现。

【输入格式】

  第一行输入一个正整数n。
  以下n行每行两个字母,表示这两个字母需要相邻。

【输出格式】

  输出满足要求的字符串。
  如果没有满足要求的字符串,请输出“No Solution”。
  如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案

【输入样例】

4
aZ
tZ
Xt
aX

【输出样例】

XaZtX

【数据范围】

不同的无序字母对个数有限,n的规模可以通过计算得到

这道题实质上是无向欧拉路径问题,需判断连个条件,一个是图要基连通,一个是除两个点以外其余点的度要为偶数。这道题我用的是邻接表,不如用邻接矩阵写起来方便。所以在欧拉路问题时可以优先考虑邻接矩阵。

#include
#include
#include
#include
using namespace std;
const int maxn=1000;
vector<int>e;
int n,d[150],s=maxn,vis[maxn];
char ch[maxn][5];

struct data
{
    int v,id;
};
vectorg[150]; 

bool cmp(data a,data b)
{
    return a.vvoid dfs(int i)
{
    for(int k=0;kint j=g[i][k].v,id=g[i][k].id;
        if(vis[id]) continue;
        vis[id]=1;
        dfs(j);
    }
    e.push_back(i);
}

bool check()
{
    int cnt=0;
    for(int i='A';i<='z';i++)
    {
        if(d[i]%2)
        {
            if(cnt==0) s=maxn;
            cnt++;
            s=min(s,i);
        }
    }
    if(cnt!=0&&cnt!=2) return 0;

    memset(vis,0,sizeof(vis));
    dfs(s);
    if(e.size()!=n+1) return 0;
    return 1;
}

int main()
{
    //freopen("1.txt","r",stdin);
    scanf("%d",&n);
    memset(d,0,sizeof(d));
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ch[i]);
        g[ch[i][0]].push_back((data){ch[i][1],i});
        g[ch[i][1]].push_back((data){ch[i][0],i});
        d[ch[i][1]]++,d[ch[i][0]]++;
        s=min(s,(int)ch[i][0]),s=min(s,(int)ch[i][1]);
    }
    for(int i='A';i<='z';i++)
    {
        sort(g[i].begin(),g[i].end(),cmp);
    }

    if(check())
    {
        for(int i=e.size()-1;i>=0;i--)
        printf("%c",e[i]);
    }
    else printf("No Solution\n"); 
    return 0;
}

你可能感兴趣的:(欧拉路)