1. 程式人生 > 實用技巧 >洛谷P1341《無序字母對》

洛谷P1341《無序字母對》

原更新日期:2019-01-21 17:11:55

尤拉圖板子題

題目描述

給定n個各不相同的無序字母對(區分大小寫,無序即字母對中的兩個字母可以位置顛倒)。請構造一個有n+1個字母的字串使得每個字母對都在這個字串中出現。

輸入輸出格式

輸入格式

第一行輸入一個正整數n。

以下n行每行兩個字母,表示這兩個字母需要相鄰。

輸出格式

輸出滿足要求的字串。

如果沒有滿足要求的字串,請輸出“No Solution”。

如果有多種方案,請輸出前面的字母的ASCII編碼儘可能小的(字典序最小)的方案

輸入輸出樣例

輸入樣例

4
aZ
tZ
Xt
aX

輸出樣例

XaZtX

說明

【資料規模與約定】

不同的無序字母對個數有限,n的規模可以通過計算得到。

解題思路

我們考慮把每一對字母視為一條邊
那麼這個圖就是無向的(因為字母對是無序的)

題目讓你求一個串,使得這個串裡出現了所有的字母對,實際上就是讓你求一條路徑,使得所有的邊都出現過

那這不就是求尤拉路嗎!

所以這道題就完美地被轉換為了尤拉路板子題

沒學過尤拉路的看這裡

程式碼實現

/* -- Basic Headers -- */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>

/* -- STL Iterators -- */
#include <vector>
#include <string>
#include <stack>
#include <queue>

/* -- External Headers -- */
#include <map>
#include <cmath>

/* -- Defined Functions -- */
#define For(a,x,y) for (int a = x; a <= y; ++a)
#define Forw(a,x,y) for (int a = x; a < y; ++a)
#define Bak(a,y,x) for (int a = y; a >= x; --a)

namespace FastIO {
    
    inline int getint() {
        int s = 0, x = 1;
        char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') x = -1;
            ch = getchar();
        }
        while (isdigit(ch)) {
            s = s * 10 + ch - '0';
            ch = getchar();
        }
        return s * x;
    }
    inline void __basic_putint(int x) {
        if (x < 0) {
            x = -x;
            putchar('-');
        }
        if (x >= 10) __basic_putint(x / 10);
        putchar(x % 10 + '0');
    }
    
    inline void putint(int x, char external) {
        __basic_putint(x);
        putchar(external);
    }
}


namespace Solution {
    const int MAXN = 256 + 233;
    
    int n;
    int G[MAXN][MAXN], deg[MAXN];
    char __MIN_NODE = 127, __MAX_NODE = 0;
    
    std::stack<char> stk;
    
    inline void addEdge(char prev, char next, bool Undirected = true) {
        ++G[prev][next];
        if (Undirected) addEdge(next, prev, false);
    }
    
    inline void deleteEdge(char prev, char next, bool Undirected = true) {
        --G[prev][next];
        if (Undirected) deleteEdge(next, prev, false);
    }
    
    inline void Hierholzer(char s) {
        for (char i = __MIN_NODE; i <= __MAX_NODE; ++i) {
            if (G[s][i]) {
                deleteEdge(s, i);
                Hierholzer(i);
            }
        }
        stk.push(s);
    }
}

signed main() {
#define HANDWER_FILE
#ifndef HANDWER_FILE
    freopen("testdata.in", "r", stdin);
    freopen("testdata.out", "w", stdout);
#endif
    using namespace Solution;
    std::ios::sync_with_stdio(false);
    std::cin >> n;
    For (i, 1, n) {
        char prev, next;
        std::cin >> prev;
        std::cin >> next;
        addEdge(prev, next);
        ++deg[prev];
        ++deg[next];
        __MIN_NODE = std::min(__MIN_NODE, std::min(prev, next));
        __MAX_NODE = std::max(__MAX_NODE, std::max(prev, next));
    }
    int odd = 0;
    char start = 0;
    for (char i = __MIN_NODE; i <= __MAX_NODE; ++i) {
        if (deg[i] != 0 && deg[i] % 2 == 1) {
            if (!start) start = i;
            ++odd;
        }
    }
    if (!start) start = __MIN_NODE;
    if (odd && odd != 2) {
    	// 注意不要忘了判無解
        std::cout << "No Solution" << std::endl;
        return 0;
    }
    Hierholzer(start);
    while (!stk.empty()) {
        std::cout << stk.top();
        stk.pop();
    }
    return 0;
}