Codeforces Round #288 (Div. 2) D. Tanya and Password 欧拉回路

来源:互联网 发布:万方数据库高级检索 编辑:程序博客网 时间:2024/06/04 19:15

D. Tanya and Password
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
While dad was at work, a little girl Tanya decided to play with dad’s password to his secret database. Dad’s password is a string consisting of n + 2 characters. She has written all the possible n three-letter continuous substrings of the password on pieces of paper, one for each piece of paper, and threw the password out. Each three-letter substring was written the number of times it occurred in the password. Thus, Tanya ended up with n pieces of paper.

Then Tanya realized that dad will be upset to learn about her game and decided to restore the password or at least any string corresponding to the final set of three-letter strings. You have to help her in this difficult task. We know that dad’s password consisted of lowercase and uppercase letters of the Latin alphabet and digits. Uppercase and lowercase letters of the Latin alphabet are considered distinct.

Input
The first line contains integer n (1 ≤ n ≤ 2·105), the number of three-letter substrings Tanya got.

Next n lines contain three letters each, forming the substring of dad’s password. Each character in the input is a lowercase or uppercase Latin letter or a digit.

Output
If Tanya made a mistake somewhere during the game and the strings that correspond to the given set of substrings don’t exist, print “NO”.

If it is possible to restore the string that corresponds to given set of substrings, print “YES”, and then print any suitable password option.

Sample test(s)
input
5
aca
aba
aba
cab
bac
output
YES
abacaba
input
4
abc
bCb
cb1
b13
output
NO
input
7
aaa
aaa
aaa
aaa
aaa
aaa
aaa
output
YES
aaaaaaaaa
题意,给出一个字符串的每三位所得到的n-2个字符串(顺序打乱)要求原来的那个字符串!
以每个字符串的前两个 后两个看成点,连条线,建成图,原问题就转化成了要求过每条边一次的路径,也就是欧拉通路,判定欧拉通路要求全部是偶度点或者只有两个奇度点,且这两个点,一个出度比入度大一,就是起点,一个出度比入度小一,就是终点,使用Fleury算法,注意,图不一定连通,且如果自已连自已的边可以使用数组记录下来,优化一下!因为每条边只经过一次,复杂度O(m),m是边数!

#define INF         9000000000#define EPS         (double)1e-9#define mod         1000000007#define PI          3.14159265358979//*******************************************************************************/#endif#define N 200050#define M 4005#define maxn 205#define MOD 1000000000000000007struct edge{    int s,e,in;    edge(){    }    edge(int ss,int ee,int inn){        s = ss;e = ee;in = inn;    }};int n,ansi,dp[M],in[N],out[N];bool vis[N];char str[N][4],ans[N];vector<edge> p[M];int charNum(char a){    if(a>='a' && a<='z') return a-'a';    if(a>='A' && a<='Z') return a-'A' + 26;    if(a>='0' && a<='9') return a-'0' + 52;    return 0;}char enchar(int a){    if(a<26){return a+'a';}    else if(a<52){return a-26+'A';}    else {return a-52 + '0';}}int SumNum(char a,char b){    return charNum(a) * 62 + charNum(b);}void DFS(int pos){    printf("%d \n",pos);    FJ(p[pos].size()){        if(!vis[p[pos][j].in] )        {            vis[p[pos][j].in] = true;            DFS(p[pos][j].e);            p[pos].erase(p[pos].begin() + j);            j--;        }    }    if(dp[pos]>0){        FI(dp[pos]){            ans[ansi++] = enchar(pos%62);        }        dp[pos] = 0;    }    ans[ansi++] = enchar(pos%62);}int main(){    while(S(n)!=EOF)    {        memset(vis,false,sizeof(vis));        memset(in,0,sizeof(in));        memset(out,0,sizeof(out));        memset(dp,0,sizeof(dp));        FI(M) p[i].clear();        FI(n){            SS(str[i]);            int s1 = SumNum(str[i][0],str[i][1]);            int s2 = SumNum(str[i][1],str[i][2]);            if(s1 != s2){                p[s1].push_back(edge(s1,s2,i));                out[s1]++,in[s2]++;            }            else {                dp[s1]++;            }        }        int flag = 0,start = -1,end = -1;        FI(M){            if(in[i] != out[i]){               flag ++;               if(end == -1 && in[i] == out[i] + 1){                    end = i;               }               else if(start == -1 && in[i]+1 == out[i]){                    start = i;               }               else {                    flag = 3;               }            }        }        if(flag == 0 || flag == 2){            if(start == -1) start = SumNum(str[0][0],str[0][1]);            ansi = 0;            DFS(start);            ans[ansi++] = enchar(start/62);            if(ansi != n+2) {                printf("NO\n");                continue;            }            printf("YES\n");            for(int i=ansi-1;i>=0;i--) printf("%c",ans[i]);            printf("\n");        }        else {            puts("NO");        }    }    return 0;}
0 0
原创粉丝点击