传送门:题源较多,大家可以到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; }