标签:
某年某月某日,韩爷被妹子表白了\o/
同时,韩爷收到了来自妹子的情书。在好奇心的驱使下,众人想要一览究竟。 显然,羞涩韩爷是不会把情书直接拿出来的。 假设情书长度为n+2,韩爷从中提取出n个长度为3的连续字符串,分给了n个人。
现在这n个人向你求助,能否帮他们把情书恢复出来。
第一行一个数字 n (1≤n≤2⋅105)表示有n个字符串
接下来n行,每行是三个字符组成的字符串。字符可能是小写字母、大写字母或数字。
注意可能会有相同的字符串。
如果韩爷耍了小聪明的,即所求的字符串并不存在,输出NO
否则,输出YES
,并且输出任意一个可能的字符串。
Sample Input | Sample Output |
---|---|
4 baa caa aax aay |
NO |
5 123 234 345 456 567 |
YES 1234567 |
3 123 231 312 |
YES 23123 |
当字符串存在时,字符串可能不唯一,比如样例3下,12312、31231也是符合题意的。
解题报告:
这是一道有向图欧拉路存在问题的题目.
我们可以很容易想到题目的边是两个单词一组建边,我们采用 2 位的62进制来表示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\n"); 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\n"); return 0; } printf("YES\n"); 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("\n"); return 0; }
UESTC_韩爷的情书 2015 UESTC Training for Graph Theory<Problem H>
标签:
原文地址:http://www.cnblogs.com/Xiper/p/4570663.html