luogu1341 无序字母对

题目大意

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

题解

  首先由n+1可以想到什么?一条条边首尾相接,端点数便是边数+1。所以这道题就是一个欧拉路径问题。

  欧拉路径的判定:度数为奇数的点为0个或2个。

  欧拉路径的遍历:从一个度数为奇数的点(有度数为奇数的点的情况)或任意一点(无度数为奇数的点的情况)开始Dfs,存在没有被访问的边就沿边Dfs下去(节点可以重复走),最后将节点按Dfs逆后序输出即为答案。

  如何满足字典序最小:我们按照逆后序输出,我们应当让每个节点的出边节点编号递增,这样可以使得先Dfs到编号低的节点,过后再从编号高的节点回来,使得编号高的节点先入栈,逆后序输出时编号高的节点会越靠后。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
using namespace std;

#define Char_Inten(c) (c >= 'a' ? c - 'a' + 27 : c - 'A' + 1)
#define Int_Charten(x) (x <= 26 ? x - 1 + 'A' : x - 27 + 'a')
const int MAX_NODE = 100, MAX_EDGE = MAX_NODE * MAX_NODE, INF = 0x3f3f3f3f;
bool IntenCharVis[MAX_NODE];
int IntenChar_NodeId[MAX_NODE], NodeId_IntenChar[MAX_NODE];
int TotNode;

struct ElurianGraph
{
private:
    struct Node;
    struct Edge;

    struct Node
    {
        Edge *Head;
        int Degree;
        //bool Vis;
    }_nodes[MAX_NODE], *Start, *Target;
    int _vCount;

    struct Edge
    {
        Edge *Next, *Rev;
        Node *From, *To;
        bool Vis;
    }_edges[MAX_EDGE];
    int _eCount;
    stack<Edge*> EdgeSt;

    Edge *AddEdge(Node *from, Node *to)
    {
        Edge *e = _edges + ++_eCount;
        e->From = from;
        e->To = to;
        Node *prevTo = NULL;
        Edge **InsNext = &from->Head;
        while (true)
        {
            if (!*InsNext || (prevTo <= e->To && e->To <= (*InsNext)->To))
            {
                e->Next = *InsNext;
                *InsNext = e;
                break;
            }
            else
            {
                prevTo = (*InsNext)->To;
                InsNext = &(*InsNext)->Next;
            }
        }
        return e;
    }

    void Dfs(Node *cur)
    {
        _printf("Visiting %d
", cur - _nodes);
        //if (cur->Vis)
        //	return;
        //cur->Vis = true;
        for (Edge *e = cur->Head; e; e = e->Next)
        {
            if (!e->Vis)
            {
                e->Vis = e->Rev->Vis = true;
                Dfs(e->To);
                EdgeSt.push(e);
            }
        }
    }

public:
    void Init(int n)
    {
        _vCount = n;
        _eCount = 0;
        Start = Target = NULL;
    }

    void Build(int u, int v)
    {
        Edge *e1 = AddEdge(_nodes + u, _nodes + v);
        Edge *e2 = AddEdge(_nodes + v, _nodes + u);
        e1->Rev = e2;
        e2->Rev = e1;
        _nodes[u].Degree++;
        _nodes[v].Degree++;
    }

    bool IsConnect()
    {
        for (int i = 1; i <= _vCount; i++)
        {
            if (_nodes[i].Degree & 1)
            {
                if (Target)
                    return false;
                else if (Start)
                {
                    Target = _nodes + i;
                    if (Start > Target)
                        swap(Start, Target);
                }
                else
                    Start = _nodes + i;
            }
        }
        bool ans = (Start && Target) || !(Start || Target);
        if (!Start)
            Target = Start = _nodes + 1;
        return ans;
    }

    int *GetOrder()
    {
        int *ans = new int[MAX_EDGE];
        Dfs(Start);
        int i = 0;
        ans[++i] = EdgeSt.top()->From - _nodes;
        while (!EdgeSt.empty())
        {
            ans[++i] = EdgeSt.top()->To - _nodes;
            EdgeSt.pop();
        }
        ans[++i] = 0;
        return ans;
    }
}g;

void GetChar_NodeId()
{
    TotNode = 0;
    for (int intenChar = 1; intenChar <= 52; intenChar++)
        if (IntenCharVis[intenChar])
        {
            IntenChar_NodeId[intenChar] = ++TotNode;
            NodeId_IntenChar[TotNode] = intenChar;
        }
}

int main()
{
    int n;
    scanf("%d", &n);
    static char ss[MAX_EDGE][10];
    for (int i = 1; i <= n; i++)
    {
        scanf("%s", ss[i] + 1);
        IntenCharVis[Char_Inten(ss[i][1])] = IntenCharVis[Char_Inten(ss[i][2])] = true;
    }
    GetChar_NodeId();
    g.Init(TotNode);
    for (int i = 1; i <= n; i++)
        g.Build(IntenChar_NodeId[Char_Inten(ss[i][1])], IntenChar_NodeId[Char_Inten(ss[i][2])]);
    if (!g.IsConnect())
    {
        printf("No Solution
");
        return 0;
    }
    int *ans = g.GetOrder();
    for (int i = 1; ans[i]; i++)
        printf("%c", Int_Charten(NodeId_IntenChar[ans[i]]));
    printf("
");
    return 0;
}

  

原文地址:https://www.cnblogs.com/headboy2002/p/9439683.html