POJ_2513_Trie树+欧拉回路+并查集

Trie树用在字符串查找排序上。http://dongxicheng.org/structure/trietree/

1.把木棒的端点考虑为顶点,木棒考虑为边,建立起一个无向图。 

2.问题转化为在无向图上判断是否有欧拉回路或者欧拉道路。 

3.在无向图上判断是否有欧拉回路或者欧拉道路:欧拉定理+并查集(判断连通性) 

4.考虑如何统计每个顶点的度,开始用的是暴力解法,直接用数组记录顶点,并且通过顺序查找获得顶点编号,TLE,然后考虑用map(红黑树),每次以logn的时间复杂度完成顶点度的  更新,继续TLE,想到用HASH,不过没想到好的映射方式,最后搜解题报告,发现trie树这种玩意。 

6.Trie树能以O(sizeof(key))的时间复杂度完成字符串的查找,所以每次更新顶点度的时间复杂度可以优化为O(1),这样应该不会超时。 

7.Trick:在没有任何木条时,应该输出Possible. 

8.静态实现Trie比动态实现Trie更快。 

9.实现代码(动态+递归): 

Cpp代码  

  1. #include<iostream>  
  2.     #include<cstdio>  
  3.     #include<cstring>  
  4.     using namespace std;  
  5.     const int MAXN = 500001;  
  6.     int p[MAXN],maxv=0,deg[MAXN];  
  7.     void init()  
  8.     {  
  9.          for(int i=0;i<MAXN;i++)  
  10.          p[i] = i,deg[i]=0;  
  11.     }  
  12.     int find(int x)  
  13.     {  
  14.         return x==p[x]?x:p[x]=find(p[x]);  
  15.     }  
  16.     void merge(int x,int y)  
  17.     {  
  18.          int r1 = find(x),r2 = find(y);  
  19.          if(r1==r2)return;  
  20.          p[r1] = r2;  
  21.     }  
  22.     bool Euler()  
  23.     {  
  24.          int cnt = 0;  
  25.          for(int i=0;i<maxv;i++)  
  26.          {  
  27.              if(deg[i]&1) cnt++;  
  28.          }  
  29.          return cnt==0||cnt==2;  
  30.     }  
  31.     bool conn()  
  32.     {  
  33.          int cnt = 0;  
  34.          for(int i=0;i<maxv;i++)  
  35.          {  
  36.              if(p[i]==i)cnt++;  
  37.          }  
  38.          if(cnt==1)return true;  
  39.          else return false;  
  40.     }  
  41.     struct node  
  42.     {  
  43.         int id;  
  44.         node* next[26];  
  45.         node()  
  46.         {  
  47.             for(int i=0;i<26;i++)  
  48.             next[i] = NULL;  
  49.             id = -1;  
  50.         }  
  51.     };  
  52.     struct trie  
  53.     {  
  54.        node *root;  
  55.        int wordnum;  
  56.        trie()  
  57.        {  
  58.            root = new node();  
  59.            wordnum = 0;  
  60.        }  
  61.        ~trie()  
  62.        {  
  63.            clear(root);  
  64.        }  
  65.        void clear(node *cur)  
  66.        {  
  67.             for(int i=0;i<26;i++)  
  68.             {  
  69.                 if((*cur).next[i]!=NULL)  
  70.                 {  
  71.                    clear((*cur).next[i]);  
  72.                    delete (*cur).next[i];  
  73.                    (*cur).next[i]=NULL;  
  74.                 }  
  75.             }  
  76.        }  
  77.        int find(char *key,int cur,node *curr,int len)  
  78.        {  
  79.             if(cur==len)  
  80.             {         
  81.                if(curr->id==-1)return -1;//没找到   
  82.                return curr->id;     
  83.             }  
  84.             int site = key[cur]-‘a’;  
  85.             if((*curr).next[site]==NULL)  
  86.             {  
  87.                  return -1;  
  88.             }//没找到  
  89.             return find(key,cur+1,(*curr).next[site],len);   
  90.        }  
  91.        void insert(char *key,int cur,node *curr,int len)  
  92.        {  
  93.             if(cur==len)  
  94.             {  
  95.                 curr->id = wordnum++;  
  96.                 return;  
  97.             }  
  98.             int site = key[cur]-‘a’;  
  99.             if((*curr).next[site]==NULL)  
  100.             {  
  101.                 (*curr).next[site] = new node();  
  102.             }  
  103.             insert(key,cur+1,(*curr).next[site],len);  
  104.        }  
  105.     };  
  106.     int main()  
  107.     {  
  108.         int i=0;  
  109.         char f[12],s[12];  
  110.         trie tree;  
  111.         init();  
  112.         while(1)  
  113.         {  
  114.             for(i=0;~(f[i]=getchar())&&f[i]!=‘ ‘;i++);  
  115.             if(f[i]==-1)break;  
  116.             f[i] = 0;  
  117.             for(i=0;(s[i]=getchar())!=‘\n’;i++);  
  118.             s[i] = 0;  
  119.             int u,v;  
  120.             u = tree.find(f,0,tree.root,strlen(f));  
  121.             if(u==-1)  
  122.             {  
  123.                 tree.insert(f,0,tree.root,strlen(f));  
  124.                 u = tree.wordnum-1;  
  125.                 deg[u] = 1;  
  126.             }  
  127.             else deg[u]++;  
  128.             v = tree.find(s,0,tree.root,strlen(s));  
  129.             if(v==-1)  
  130.             {  
  131.                 tree.insert(s,0,tree.root,strlen(s));  
  132.                 v = tree.wordnum-1;  
  133.                 deg[v] = 1;  
  134.             }  
  135.             else deg[v]++;   
  136.             merge(u,v);  
  137.         }  
  138.         maxv = tree.wordnum;  
  139.         if(maxv==0){  
  140.            printf(“Possible\n”);  
  141.            return 0;  
  142.         }  
  143.         bool ok = Euler()&&conn();  
  144.         if(ok) printf(“Possible\n”);  
  145.         else printf(“Impossible\n”);  
  146.         return 0;  
  147.     }  

10.静态实现+迭代,代码: 

Cpp代码  

  1. #include<iostream>  
  2.     #include<cstring>  
  3.     #include<cstdio>  
  4.     using namespace std;  
  5.     struct trie_node  
  6.     {  
  7.         int id;  
  8.         int next[26];  
  9.         trie_node()  
  10.         {  
  11.             for(int i=0;i<26;i++)next[i] = 0;  
  12.             id = -1;  
  13.         }  
  14.     }trie[700000];  
  15.     const int MAXN = 500002;  
  16.     int p[MAXN],deg[MAXN],maxv=0,trieM=2;  
  17.     void init()  
  18.     {  
  19.         for(int i=0;i<MAXN;i++)p[i]=i;  
  20.     }  
  21.     int find(int x)  
  22.     {  
  23.         return x==p[x]?x:p[x]=find(p[x]);  
  24.     }  
  25.     void merge(int x,int y)  
  26.     {  
  27.          int r1 = find(x),r2 = find(y);  
  28.          if(r1==r2)return;  
  29.          p[r1] = r2;  
  30.     }  
  31.     int insert(char *word)  
  32.     {  
  33.         int now;  
  34.         int ptr = 1;  
  35.         char *p = word;  
  36.         while(*p)  
  37.         {  
  38.             now = *p-‘a’;  
  39.             if(!trie[ptr].next[now])trie[ptr].next[now]=trieM++;  
  40.             ptr = trie[ptr].next[now];  
  41.             p++;  
  42.         }  
  43.         //如果没有该元素   
  44.         if(trie[ptr].id==-1)  
  45.         {  
  46.             trie[ptr].id = maxv++;  
  47.         }  
  48.         return trie[ptr].id;  
  49.     }  
  50.     bool conn()  
  51.     {  
  52.          int cnt = 0;  
  53.          for(int i=0;i<maxv;i++)  
  54.          if(p[i]==i)cnt++;  
  55.          return cnt==1;  
  56.     }  
  57.     bool euler()  
  58.     {  
  59.          int cnt = 0;  
  60.          for(int i=0;i<maxv;i++)  
  61.          {  
  62.              if(deg[i]&1)cnt++;  
  63.          }  
  64.          return cnt==0||cnt==2;  
  65.     }  
  66.     int main()  
  67.     {  
  68.         char f[11],s[11];  
  69.         init();  
  70.         while(scanf(“%s%*c%s%*c”,f,s)!=EOF)  
  71.         {  
  72.             int u = insert(f);  
  73.             int v = insert(s);  
  74.             deg[u]++,deg[v]++;  
  75.             merge(u,v);  
  76.         }  
  77.         if(maxv==0)puts(“Possible”);  
  78.         else  
  79.         {  
  80.             bool ok = euler()&&conn();  
  81.             if(ok) puts(“Possible”);  
  82.             else puts(“Impossible”);  
  83.         }  
  84.         return 0;  
  85.     }  
  86.       
    原文作者:Trie树
    原文地址: https://blog.csdn.net/zhangmengjlu/article/details/8714990
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞