POJ 2513 TRIE树+并查集+欧拉路

题意:

给定许多根木棒,两边分别涂有不同颜色,问能否将他们连成一条直线。规定只能将相同颜色的两端相连。

思路:

用TRIE树储存单词,TRIE树最后一个字母的节点编号就是这个单词的编号(可以和<map>类比)

并查集检查是否连通——有欧拉路的前提是图连通

最后加上无向图欧拉路的判定就好了~奇数度的节点只能有0或2个

 

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <string>
  5 #include <iostream>
  6 
  7 #define N 300000
  8 #define BUG system("pause")
  9 
 10 using namespace std;
 11 
 12 struct TRIE
 13 {
 14     bool bot;
 15     int son[28];
 16 }trie[N*5];
 17 
 18 char sa[N][12],sb[N][12];
 19 int num,cnt,now,wd[N*8],bh[N][2],fa[N*8];
 20 bool fg[N*8];
 21 
 22 void init()
 23 {
 24     for(int i=0;i<26;i++) trie[0].son[i]=-1;
 25     num=0;
 26 }
 27 
 28 void insert(char a[])
 29 {
 30     now=0;
 31     int len=strlen(a+1);
 32     for(int i=1;i<=len;i++)
 33     {
 34         if(trie[now].son[a[i]-'a']==-1)
 35         {
 36             num++;
 37             for(int j=0;j<26;j++) trie[num].son[j]=-1;
 38             trie[num].bot=false;
 39             trie[now].son[a[i]-'a']=num;
 40         }
 41         now=trie[now].son[a[i]-'a'];
 42     }
 43     trie[now].bot=true;
 44     wd[now]++;//单词出现次数 
 45     fg[now]=true;
 46 }
 47 
 48 int findfa(int x)
 49 {
 50     if(x!=fa[x]) fa[x]=findfa(fa[x]);
 51     return fa[x];
 52 }
 53 
 54 bool judge()
 55 {
 56     int cs=0,cf=0;
 57     memset(fg,0,sizeof fg);
 58     for(int i=1;i<=cnt;i++)
 59     {
 60         if((wd[bh[i][0]]&1)&&!fg[bh[i][0]]) cs++,fg[bh[i][0]]=true;
 61         if((wd[bh[i][1]]&1)&&!fg[bh[i][1]]) cs++,fg[bh[i][0]]=true;
 62     }
 63     memset(fg,0,sizeof fg);
 64     
 65     if(cs==1||cs>2) return false;
 66     
 67     for(int i=1;i<=num;i++) fa[i]=i; 
 68     
 69     for(int i=1;i<=cnt;i++)
 70     {
 71         fg[bh[i][0]]=fg[bh[i][1]]=true;
 72         if(findfa(bh[i][0])!=findfa(bh[i][1]))
 73             fa[findfa(bh[i][0])]=findfa(bh[i][1]);
 74     }
 75     for(int i=1;i<=num;i++)
 76         if(fg[i])
 77         {
 78             if(cf==0) cf=findfa(i);
 79             else if(cf!=findfa(i)) return false;
 80         }
 81         
 82     return true;
 83 }
 84 
 85 void go()
 86 {
 87     if(judge()) puts("Possible");
 88     else puts("Impossible");
 89 }
 90 
 91 void read()
 92 {
 93     cnt=1;
 94     while(scanf("%s%s",sa[cnt]+1,sb[cnt]+1)!=EOF)
 95     {
 96         insert(sa[cnt]);   bh[cnt][0]=now;
 97         insert(sb[cnt]);   bh[cnt][1]=now;
 98         cnt++;
 99     }
100     cnt--;
101 }
102 
103 int main()
104 {
105     init();
106     read();
107     go();
108     return 0;
109 }

 

好久不写trie了,因为数组开小了WA了两次,也勉强给自己一个1A吧~嘿嘿

posted @ 2012-10-07 22:03  proverbs  阅读(200)  评论(0编辑  收藏  举报