zoukankan      html  css  js  c++  java
  • UESTC_韩爷的情书 2015 UESTC Training for Graph Theory<Problem H>

    H - 韩爷的情书

    Time Limit: 6000/2000MS (Java/Others)     Memory Limit: 262144/262144KB (Java/Others)
     

    某年某月某日,韩爷被妹子表白了o/

    同时,韩爷收到了来自妹子的情书。在好奇心的驱使下,众人想要一览究竟。 显然,羞涩韩爷是不会把情书直接拿出来的。 假设情书长度为n+2,韩爷从中提取出n个长度为3的连续字符串,分给了n个人。

    现在这n个人向你求助,能否帮他们把情书恢复出来。

    Input

    第一行一个数字 n (1n2105)表示有n个字符串

    接下来n行,每行是三个字符组成的字符串。字符可能是小写字母、大写字母或数字。

    注意可能会有相同的字符串。

    Output

    如果韩爷耍了小聪明的,即所求的字符串并不存在,输出NO

    否则,输出YES,并且输出任意一个可能的字符串。

    Sample input and output

    Sample InputSample Output
    4
    baa
    caa
    aax
    aay
    NO
    5
    123
    234
    345
    456
    567
    YES
    1234567
    3
    123
    231
    312
    YES
    23123

    Hint

    当字符串存在时,字符串可能不唯一,比如样例3下,12312、31231也是符合题意的。

    解题报告:

    这是一道有向图欧拉路存在问题的题目.

     我们可以很容易想到题目的边是两个单词一组建边,我们采用 2 位的62进制来表示2个单词这个点,之后建立有向图,同时还要建立一次无向图.

    1. 首先判定原图是否连通,跑一次dfs即可
    2. 之后跑一次全图的度数,欧拉路存在的条件是

    <1>.所有点的入度 = 出度

    <2>有一个点的入度 – 出度 = 1 , 一个点 入度 – 出度 = - 1,其他点入度 = 出度.

    通过 2 ,可以很容易确定起点(入度 – 出度 = -1 ,或者第一种情况的话任意点都行),跑一次dfs,把边压栈,最后打印即可

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <map>
    #include <vector>
    #include <stack>
    #define pb push_back
    /*
    
    #ifdef DIABLO 3 
     嘲笑命运这幽默的安排 
    #endif
    
    */
    
    #ifndef outedge
    
    typedef struct Edge
    {
       char s1,s2;
       int  v;
       Edge(const char* s1,const char *s2,const int *v)
        {
            this->s1 = *s1 , this->s2 = *s2 , this->v = *v;
        }
    };
    
    #endif
    
    using namespace std;
    const int maxn = 65 * 65;
    const int limit = 62 * 62;
    const char * all = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    const int length = strlen(all);
    map<char,int>pos;
    int n,indig[maxn],outdig[maxn];
    char buffer[10];
    vector<Edge>DE[maxn]; //有向边
    vector<Edge>UE[maxn]; //无向边
    vector<int>s1; // indig - outdig = 1
    vector<int>s2; // indig - outdig = -1
    stack<char>out;
    bool use[maxn],arrive[maxn];
    char hashstring[maxn][2];
    
    
    // 62进制压缩 
    inline int HashValue(const char *st)
    {
       return 62*pos[st[0]] + pos[st[1]];
    }
    
    void init_letter_table()
    {
       int tot = 0;
       for(int i = 0 ; i < 26 ; ++ i)
        pos[char(i+'a')] = tot++;
       for(int i = 0 ; i < 26 ; ++ i)
        pos[char(i+'A')] = tot++;
       for(int i = 0 ; i < 10 ; ++ i)
        pos[char(i+'0')] = tot++;
    }
    
    void dfs(int cur)
    {
       arrive[cur] = true;
       for(int i = 0 ; i < UE[cur].size() ; ++ i)
        {
           int nextnode = UE[cur][i].v;
           if (!arrive[nextnode])
            dfs(nextnode);
        }
    }
    
    
    bool judge()
    {
       if (s1.size() != s2.size())
        return false;
       else if(s1.size() >= 2 || s2.size() >= 2)
        return false;
       return true;
    }
    
    
    void print_ans(int cur)
    {
       char x1 = hashstring[cur][0];
       char x2 = hashstring[cur][1];
       while(DE[cur].size())
        {
           int nextnode = DE[cur][DE[cur].size() - 1].v;
           char x3 = hashstring[nextnode][1];
           DE[cur].pop_back();//删边 
           print_ans(nextnode);
           out.push(x3);
        }
    }
    
    int main(int argc,char *argv[])
    {
      init_letter_table();
      memset(arrive,false,sizeof(arrive));memset(use,false,sizeof(use));memset(indig,0,sizeof(indig));memset(outdig,0,sizeof(outdig));
      scanf("%d",&n);
      int beginteger;
      for(int i = 0 ; i < n ; ++ i)
       {
             scanf("%s",buffer);
             int t1 = HashValue(buffer) , t2 = HashValue(buffer + 1);
             use[t1] = true , use[t2] = true; 
             beginteger = t1;
             hashstring[t1][0] = buffer[0] , hashstring[t1][1] = buffer[1] , hashstring[t2][0] = buffer[1] , hashstring[t2][1] = buffer[2];
             UE[t1].pb(Edge(buffer,buffer+1,&t2)) , UE[t2].pb(Edge(buffer,buffer+1,&t1)); //无向边连接
             DE[t1].pb(Edge(buffer,buffer+1,&t2)); //有向边连接
          outdig[t1] ++ , indig[t2] ++ ; 
       }
      dfs(beginteger); //连通性测试 
      int check = 1;
      for(int i = 0 ; i < limit ; ++ i)
       if(use[i] == true &&  arrive[i] == false)
        check = 0;
      if (!check) //图不连通 
       {
             printf("NO
    ");
             return 0;
       }
      for(int i = 0 ; i < limit ; ++ i)
       if(use[i])
        {
            int x = indig[i] - outdig[i];
            if (x == 0) continue;
            else if(x == 1) s1.pb(i);
            else if(x == -1) s2.pb(i);
            else check = 0;
        }
      if (!check || !judge()) //非法 
        {
           printf("NO
    ");
           return 0;
        }
      printf("YES
    ");
      if (s2.size()==1)
       beginteger = s2[0];
      print_ans(beginteger);
      printf("%c%c",hashstring[beginteger][0],hashstring[beginteger][1]);
      while(!out.empty())
       {
             printf("%c",out.top());
          out.pop(); 
       }
      printf("
    ");
      return 0;
    }
  • 相关阅读:
    5.22 css和基本选择器
    5.21http网页基础
    ArrayList类源码浅析(二)
    ArrayList类源码浅析(一)
    Long类源码浅析
    Integer类源码浅析
    JDK中String类的源码分析(二)
    JDK中String类的源码分析(一)
    Struts2漏洞修复总结
    [LeetCode]-011-Longest Common Prefix
  • 原文地址:https://www.cnblogs.com/Xiper/p/4570663.html
Copyright © 2011-2022 走看看