传送门:题源较多,大家可以到BNU上搜下Kid's Wishes。
提议:有还多孩子,和很多愿望,每个愿望有2个数字,代表前一个编号的孩子和后一个坐相邻,问所有愿望实现,能都坐成一个圈。
思路:虽然孩子数量很大,但是愿望数并不是那么多,这里就不采用它的编号了,而是根据孩子出现的顺序重新编号,一开始用的map。这种方法在UVALive上可以过,不过在中山大学的oj就超时了,后来改成Trie树哈希做,就过了。
刚刚只是对编号的处理,下面考虑坐圈,在一个圈中,一个孩子最多和两个孩子相邻,如果出现第三个,则一定不可以。
还有在途中找圈,要么找不到,要么是所有孩子围成的圈,其它小圈则说明也不可以,这样一考虑就差不多了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
int num;
int fst[222222],next[222222],node[222222],en;
int d[222222];
int cnt[222222];
int m,n,tnum;
bool vis[222222];
bool flag;
struct Trie
{
int c[11];
int id;
}t[2222222];
void init()
{
en=0;
num=0;
tnum=0;
flag=0;
memset(fst,-1,sizeof(fst));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
memset(t[0].c,0,sizeof(t[0].c));
}
void add(int u,int v)
{
next[en]=fst[u];
fst[u]=en;
node[en]=v;
en++;
}
int trie(char *a)
{
int l=strlen(a);
int p=0;
for(int i=0;i<l;i++)
{
if(t[p].c[a[i]-'0']==0)
{
t[p].c[a[i]-'0']=++tnum;
memset(t[tnum].c,0,sizeof(t[tnum].c));
t[tnum].id=0;
}
p=t[p].c[a[i]-'0'];
}
if(t[p].id==0)
{
t[p].id=++num;
}
return t[p].id;
}
void dfs(int u,int r)
{
vis[u]=1;
if(r==-1)d[u]=1;
else
{
d[u]=d[r]+1;
cnt[u]++;
}
for(int i=fst[u];i!=-1;i=next[i])
{
if(flag)return;
int v=node[i];
if(v==r)continue;
if(!vis[v])
{
cnt[u]++;
if(cnt[u]>2)
{
flag=1;
return;
}
dfs(v,u);
}
else if(vis[v])
{
if(d[u]-d[v]==n-1||d[v]-d[u]==n-1||d[v]==d[u]+1)continue;
else
{
flag=1;
return;
}
}
}
}
int main()
{
char s1[20],s2[20];
int u,v;
while(scanf("%d%d",&n,&m))
{
if(m==0&&n==0)break;
init();
for(int i=0;i<m;i++)
{
scanf("%s%s",s1,s2);
u=trie(s1);
v=trie(s2);
add(u,v);
add(v,u);
}
for(int i=1;i<=num;i++)
{
if(flag)break;
if(!vis[i])
{
dfs(i,-1);
}
}
if(flag)cout<<"N"<<endl;
else cout<<"Y"<<endl;
}
return 0;
}