洛谷P1341 无序字母对 题解

94 篇文章 0 订阅

题目来源:

点击打开链接

题目描述:

题目描述

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

输入输出格式

输入格式:

第一行输入一个正整数n。

以下n行每行两个字母,表示这两个字母需要相邻。

输出格式:

输出满足要求的字符串。

如果没有满足要求的字符串,请输出“No Solution”。

如果有多种方案,请输出前面的字母的ASCII编码尽可能小的(字典序最小)的方案

输入输出样例

输入样例#1:  复制
4
aZ
tZ
Xt
aX
输出样例#1:  复制
XaZtX
 





说明

【数据规模与约定】

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


解题思路:

   这题可以看作是一个判断欧拉路是否存在的问题,当输入一个字母对的时候,就从这两个字母之间连接一条双向边,然后对这张图进行判断欧拉路,因为要输出最小字典序,所以要先排序一下。欧拉路的判断就不赘述了。

代码:

#include <iostream>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>E[100];
int zh1(char x)
{
    if(x>='a'&&x<='z')return 26+int(x-'a'+1);
    else return int(x-'A'+1);
} 
char zh2(int x)
{
    if(x<=26)return char(x+'A'-1);
    else return char(x-26+'a'-1);
} 
int du[100];
bool tu[100][100];
stack<int>s;
void dfs(int v)
{
    for(int i=0;i<E[v].size();i++)
    {
        int vv=E[v][i];
        if(!tu[v][vv])
        {
            tu[v][vv]=1;
            tu[vv][v]=1;
            dfs(vv);
            s.push(vv);
        }
    }
}
int main()
{
    memset(du,0,sizeof(du));
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        string a;
        cin>>a;
        int x=zh1(a[0]),y=zh1(a[1]);
        du[x]++;
        du[y]++;
        E[x].push_back(y);
        E[y].push_back(x);
    }
    int sum=0,maxn1=1e9,maxn2=1e9;
    for(int i=1;i<=52;i++)
    {
        if(du[i]){
            maxn1=min(maxn1,i);
            if(du[i]%2!=0){
                sum++;
                maxn2=min(i,maxn2);
            }
        }
        sort(E[i].begin(),E[i].end());
    }
    if(sum!=0&&sum!=2)cout<<"No Solution"<<endl;
    else{
        if(sum==0){
            dfs(maxn1);
            s.push(maxn1);
            while(!s.empty())
            {
                cout<<zh2(s.top());
                s.pop();
            }
            cout<<endl;
        }
        else{
            dfs(maxn2);
            s.push(maxn2);
            while(!s.empty())
            {
                cout<<zh2(s.top());
                s.pop();
            }
            cout<<endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值