zoukankan      html  css  js  c++  java
  • 【洛谷P1341】无序字母对

    P1341 无序字母对

    题目链接

    根据题意,只有在每两个相邻的字母都构成一个要求的无序字母对时,才能满足要求,

    我们不妨将每个字母看成一个节点,每个无序字母对看成一个无向边,

    我们要从一个点出发,不重复地走完所有的边,

    所走的路径上的点构成的字符串即为一个合法的解

    这就转化成了求一条字典序最小的欧拉路径

    字典序就用堆搞一下就行了

    如何判断是否存在欧拉路径:

    对于无向图,

    欧拉图(存在欧拉回路):该图是连通的且每个点的度数都是偶数

    半欧拉图(存在欧拉路径):该图连通且仅有两个点的读数是奇数,这两个点即为欧拉路径的起始点

    对于有向图:

    欧拉图:该图的基图是连通的且所有点的入度等于出度

    半欧拉图:该图的基图是连通的且只有一个点的入度比出度少1(起点),只有一个点的入度比出度多1(终点)

    代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    using namespace std;
    #define N 55
    #define M 6010
    int n=52,m,du[M],path[M],num;
    int Head[N],to[M],next[M],cnt=1;
    bool u[N],vis[N],cut[M];
    inline int pos(char c){
        if('A'<=c&&c<='Z') return c-'A'+1;
        else return c-'a'+27;
    }
    inline char map(int x){
        if(1<=x&&x<=26) return x+'A'-1;
        else return x+'a'-27;
    }
    struct cmp{
        bool operator()(int a,int b){
            return to[a]>to[b];
        }
    };
    inline void add(int x,int y){
        to[++cnt]=y;
        next[cnt]=Head[x];
        Head[x]=cnt;
    }
    void dfs(int t){
        priority_queue< int , vector<int> , cmp > que;
        for(int i=Head[t];i;i=next[i])
         que.push(i);
        while(!que.empty()){
            int i=que.top();
            que.pop();
            if(!cut[i]){
                vis[to[i]]=1;
                cut[i]=cut[i^1]=1;
                dfs(to[i]);
            }
        }
        path[++num]=t;
    }
    int main()
    {
        char s[3];
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%s",s);
            int x=pos(s[0]),y=pos(s[1]);
            u[x]=u[y]=1;
            add(x,y); add(y,x);
            du[x]++; du[y]++;
        }
        bool f=0; int st=0,tot=0;
        for(int i=1;i<=n;i++){
            if(du[i]%2==1){
                tot++;
                if(!f){st=i;f=1;}
                if(tot>2){
                    puts("No Solution");
                    return 0;
                }
            }
        }
        if(tot==0)
         for(int i=1;i<=n;i++)
          if(u[i]) {
              st=i; break;
          }
        vis[st]=1;
        dfs(st);
        for(int i=1;i<=n;i++)
         if(u[i]&&!vis[i]){
            puts("No Solution");
            return 0;
         }
        num++;
        while(--num)
         putchar(map(path[num]));
        return 0;
    }
  • 相关阅读:
    c++学习笔记—二叉树基本操作的实现
    c++学习笔记—单链表基本操作的实现
    c++学习笔记—c++对txt文件的读取与写入
    c++学习笔记—动态内存与智能指针浅析
    c++学习笔记——个单词转换的map程序详解
    获取JAVA[WEB]项目相关路径的几种方法
    Oracle数据库体系结构及创建表结构
    锋利的jQuery学习总结
    SQL调优常用方法
    Oracle行转列操作
  • 原文地址:https://www.cnblogs.com/yjkhhh/p/9359521.html
Copyright © 2011-2022 走看看