Codeforces 508D Tanya and Password

来源:互联网 发布:网络证据保全公证 编辑:程序博客网 时间:2024/05/21 05:37
D. Tanya and Password
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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
5acaabaabacabbac
output
YESabacaba
input
4abcbCbcb1b13
output
NO
input
7aaaaaaaaaaaaaaaaaaaaa
output
YESaaaaaaaaa


这个题类似poj1780 也是欧拉路的题目 于是类似那个写了一个 发现t了

原因就是有一组数据

200000

zzz

zzz

zzz

...

zzz


这样是一个点 200000个边

而第i层的dfs 都访问了200000-i次边

因为第一层 从第一条开始 发现没有被标记过 顺着第一条走到第一个点 开始第二层

一直到第200000层 都是这样

然后 200000层发现没有没标记过的边了 返回第199999层之后 199999层会继续遍历已经标记过的后面的边

一直到第一层 还会便利已经被标记过的第二条到第200000条边 所以会超时

#include<bits/stdc++.h>using namespace std;struct self{    int x,y,nxt;}s[1000001];int fst[1000001];int h(char* str){    int ret = str[0]*1000+str[1];    return ret;}int g[999999];int tot;int outd[1000001],ind[1000001];int m,n,x,y;char str[4],l[4],r[4];int ret[1000001],ans;char old[1000001][4];int pos,num;int flag[1000001];int ceng;void dfs(int u){    //for(int i=fst[u];i!=-1;i=s[i].nxt)    for(int i=fst[u];i!=-1;i=fst[u])    {        if(!flag[i])        {            flag[i]=1;            //            fst[u]=s[i].nxt;            dfs(s[i].y);            ret[++ans]=i;        }    }}void print(){    if(ans<m)        printf("NO\n");    else    {        printf("YES\n");        printf("%c",old[s[ret[ans]].x][0]);        printf("%c",old[s[ret[ans]].x][1]);        for(int i=ans;i>=1;i--)            printf("%c",old[s[ret[i]].y][1]);    }}int main(){    memset(fst,-1,sizeof(fst));    scanf("%d",&m);    for(int i=1;i<=m;i++)    {        scanf("%s",str);        l[0]=str[0];l[1]=str[1];        r[0]=str[1];r[1]=str[2];        if(!g[h(l)])        {            g[h(l)]=++tot;            old[tot][0]=l[0];            old[tot][1]=l[1];        }        if(!g[h(r)])        {            g[h(r)]=++tot;            old[tot][0]=r[0];            old[tot][1]=r[1];        }        outd[g[h(l)]]++;        ind[g[h(r)]]++;        n++;        s[n].x=g[h(l)];        s[n].y=g[h(r)];        s[n].nxt=fst[g[h(l)]];        fst[g[h(l)]]=n;    }    pos=1;    int ok=1;    for(int i=1;i<=tot;i++)    {        if(outd[i]!=ind[i])            num++;        if(outd[i]==ind[i]+1)            pos=i;        if(outd[i]>ind[i]+1 || outd[i]<ind[i]-1)            ok=0;    }    if(!ok)    {        printf("NO\n");        return 0;    }    if(num!=0 && num!=2)    {        printf("NO\n");        return 0;    }    dfs(pos);    print();}


原来遍历边都是采用这样的方法 就是邻接表的遍历方法

恩看来要灵活运用啊!

 for(int i=fst[u];i!=-1;i=s[i].nxt)        if(!flag[i])        {            flag[i]=1;            dfs(s[i].y);            ans++;            ret[ans]=i;        }



0 0
原创粉丝点击