poj-2513(字典树+欧拉通路)
题意:给你n个火柴棍,每个火柴棍头和尾两种颜色,问你是否存在能够把这些火柴棍摆成一行的情况,两个相连的火柴棍的颜色需要一样;
解题思路:最初的思路是用map标记颜色,然后把每种颜色看作点,每根火柴棍看作边,求欧拉路径,然后超时了。。。看了别人的写法,想起来了自己还学过字典树来着。。。然后用字典树找就行了,快很多
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; const int maxn=500050; struct tnode { int pos; bool exsit; tnode *next[30]; tnode() { for(int i=0;i<26;i++) next[i]=NULL; pos=0;exsit=false; } }; tnode *root; int x,y; int flag; int dfn; int degree[maxn]; int f[maxn]; char s[15],t[15]; tnode* newnode() { tnode *p=new tnode; for(int i=0;i<26;i++) p->next[i]=NULL; p->pos=0;p->exsit=false; return p; } void build_trie(char *s) { tnode *p=root; int slen=strlen(s); for(int i=0;i<slen;i++) { int id=s[i]-'a'; if(p->next[id]==NULL) { p->next[id]=newnode(); } p=p->next[id]; } p->exsit=true; p->pos=++dfn; } int query(char *s) { tnode *p=root; int slen=strlen(s); for(int i=0;i<slen;i++) { int id=s[i]-'a'; p=p->next[id]; if(p==NULL) return 0; } if(p->exsit) return p->pos; } int build(char *str) { int zz=query(str); if(zz!=0) return zz; else { build_trie(str); return dfn; } } int findf(int u) { if(u==f[u]) return u; else { f[u]=findf(f[u]); return f[u]; } } void join(int x,int y) { int t1=findf(x); int t2=findf(y); if(t1!=t2) f[t2]=t1; } int main() { root=newnode(); for(int i=1;i<=maxn;i++) f[i]=i; while(scanf("%s %s",s,t)!=EOF) { int x=build(s); int y=build(t); degree[x]++;degree[y]++; join(x,y); } // cout<<dfn<<endl; int cnt=0; int fa=findf(1); for(int i=2;i<=dfn;i++) if(findf(i)!=fa) flag=1; if(flag) { printf("Impossible\n");return 0; } for(int i=1;i<=dfn;i++) { if(degree[i]!=0) { if((degree[i]&1)==1) cnt++; } } // cout<<cnt<<endl; if(cnt==1||cnt>=3) flag=1; if(flag) { printf("Impossible\n"); } else printf("Possible\n"); }