zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
  • 相关阅读:
    继承
    接口
    匿名内部类
    抽象类和接口的区别
    多态
    重载和覆写的区别|this和super区别
    Visual C# 2008+SQL Server 2005 数据库与网络开发――2.2.1 变量
    Visual C# 2008+SQL Server 2005 数据库与网络开发――2.3.1 选择语句
    Visual C# 2008+SQL Server 2005 数据库与网络开发―― 2.5错误和异常处理
    Visual C# 2008+SQL Server 2005 数据库与网络开发―― 2.3 语句
  • 原文地址:https://www.cnblogs.com/zbtrs/p/5790839.html
Copyright © 2011-2022 走看看