落谷P1341无序字母对

链接:https://www.luogu.org/problem/show?pid=1341

题目描述:

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

输入输出格式

输入格式:

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

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

输出格式:

输出满足要求的字符串。

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

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

输入输出样例

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






说明

【数据规模与约定】

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


个人感觉这还是一道比较容易看出是是欧拉回路的题目呢。。

首先,是否存在欧拉路的条件:

建图:

将字母作为图的顶点,如果两字母间存在字母对就在相应的字母所对应的顶点连上一条五向边。

题目要求的是字典序最小的欧拉通路,怎么办呢?

首先来看看欧拉通路存在的条件:

1) 该连通图的所有节点的度均为偶数。


2)该连通图的奇点仅有两个。存在一条欧拉路从其中一个奇点出发,从另一个奇点结束....


如果不满足不满足欧拉通路的条件直接就是“”No Solution”

存在的话

那么利用dfs就可以求出.题目还有一个要求就是字典序最小,显然如果度数为奇数的点为两个,那么这两个点要么就是起点或终点,因为是无向图,所以不管是从起点出发还是从终点出发都是一样的,所以选择字典序小的一遍出发即可。。

代码:

#include <cstdio>
#include <stack>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn = 100;
int map[maxn][maxn], cnt[maxn], vis[maxn][maxn];
int n, maxm = 53;
stack <int> ans;

int zhuanhua1(char c)
{
    if (c >= 'A' && c <= 'Z')
        return (int)c - 'A';
    return (int)c - 'a' + 26;
}

char zhuanhuan2(int x)
{
    if (x >= 0 && x <= 25)
        return (char)x + 'A';
    return (char)(x - 26) + 'a';
}

void euler(int u)
{
    for (int v = 0; v < maxm; v++)
        if (map[u][v] && !vis[u][v])
        {
            vis[u][v] = vis[v][u] = 1;
            euler(v);
            ans.push(v);
        }
}

int main()
{
    scanf("%d%d", &n);
    for (int i = 1; i <= n; i++)
    {
        char a, b;
        cin >> a >> b;
        int x = zhuanhua1(a), y = zhuanhua1(b);
        map[x][y] = map[y][x] = 1;
        cnt[x]++;
        cnt[y]++;
    }
    int tot = 0, min1 = 1e8, min2 = 1e8;
    for (int i = 0; i < maxm; i++)
    {
        if (cnt[i]%2==1)
        {
            tot++;
            min1 = min(min1, i);
        }
        else if (cnt[i])
            min2 = min(min2, i);
    }
    if (tot != 0 && tot != 2)
        printf("No Solution\n");
    else
    {
        int u;
        if (tot == 0)
            u = min2;
        else
            u = min1;
        euler(u);
        ans.push(u);
        while (!ans.empty())
        {
            int temp = ans.top();
            ans.pop();
            char s = zhuanhuan2(temp);
            cout << s;
        }
        printf("\n");
    }

    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值