• 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;
    }
    

      

  • 相关阅读:
    用Rails.5.2+ Vue.js做 vue-todolist app
    vue-router
    Vue.js教程--基础2(事件处理 表单输入绑定
    Vue组件(知识)
    Vue.js教程--基础(实例 模版语法template computed, watch v-if, v-show v-for, 一个组件的v-for.)
    ActiveRecord Nested Atrributes 关联记录,对嵌套属性进行CURD
    (GoRails) 自动侦测用户的时区,使用javascript 的jszt库。
    (GoRails) 如何去掉form输入框头尾的空格;何时用callbacks,gem;
    JQ each
    JQ 更改li 颜色
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9439683.html
Copyright © 2020-2023  润新知