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;
}
原文地址:https://www.cnblogs.com/Xiper/p/4570663.html