洛谷P1341 无序字母对

P1341 无序字母对

    • 229通过
    • 806提交
  • 题目提供者yeszy
  • 标签图论福建省历届夏令营
  • 难度提高+/省选-

提交该题 讨论 题解 记录

最新讨论

题目描述

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

输入输出格式

输入格式:

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

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

输出格式:

输出满足要求的字符串。

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

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

输入输出样例

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

说明

【数据规模与约定】

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

分析:因为字母对的字母可以交换,所以我们可以想象成将n个字母对通过某种变换连成一起然后一次走到通.而n个字母对,n+1个字母组成字符串,说明每个字符都必须要在字符串中出现,也就是说选定一个起点,要在两个串之间的公共部分走到终点,而且n+1个字母不允许我们重复走,所以很容易联想到欧拉道路.那么我们建图,每一个字母对之间的字母连一条无向边,一个字母当作一个顶点,每连一条边,则两点的度数+1,如果度数为奇数的点只有两个或没有,那么就存在欧拉道路,那么利用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] & 1)
        {
            tot++;
            min1 = min(min1, i);
        }
        else if (cnt[i])
            min2 = min(min2, i);
    }
    if (tot != 0 && tot != 2)
        printf("No Solution
");
    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("
");
    }

    return 0;
}
原文地址:https://www.cnblogs.com/zbtrs/p/5790839.html