POJ 2513 (Trie树+欧拉通路+并查集判断连通)

题目:http://poj.org/problem?id=2513

两个教训:

  一、输入输出用scanf、printf(好像自己已经强调很多遍了= =……)

    eg:用cin 1000MS 用scanf 400MS…………

  二、不要把string作为函数值传递参数(推广到整个STL,STL加了很多没用的功能会导致效率变低) 

     eg:此题Trie中的参数用string 4485MS 用char * 985MS…………

/* 题目大意:每个木棒头尾都有两种颜色,木棒末端颜色相同的可以连接成一条直线,问能否将所有木棒连接起来组成一条直线。 题目求解:传换成图的问题就是求解能否一笔画成(欧拉通路) 代码技巧:用数组字典树和链表字典树都可以,动态链表空间少好写,静态数组速度快,看情况吧。 */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <iomanip> #include <climits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #include <algorithm> #include <string> #include <cstring>



using namespace std; #define N 500005



struct set { int parent;  //记录父节点

    int rank;    //记录集合的节点数

}elem[N]; int MAX; void init() { int i; for(i=0;i<=N;i++) { elem[i].parent=i; elem[i].rank=1; } } int Find(int x) { int root,temp; temp=x; while(x!=elem[x].parent)    //寻找根节点

        x=elem[x].parent; root=x; x=temp; while (x!=elem[x].parent)   //压缩路径,全部赋值为根节点的值

 { temp=elem[x].parent; elem[x].parent=root; x=temp; } return root; } void Union(int a,int b)   //合并两个集合

{ int x,y; x=Find(a); y=Find(b); if(elem[x].rank>=elem[y].rank) { elem[y].parent=elem[x].parent; elem[x].rank+=elem[y].rank; if(MAX<elem[x].rank) MAX=elem[x].rank; } else { elem[x].parent=elem[y].parent; elem[y].rank+=elem[x].rank; if(MAX<elem[y].rank) MAX=elem[y].rank; } } //Trie树模板 by AbandonZHANG





int words_num; int degree[500005]; struct Trie_node { //int Ch_Count; //统计单词个数,如果为0表示没有该串。

    int hash;       //单词hash后的标识数

    Trie_node *next[26];//指向各个子树的指针,下标0-25代表26字符,如果是数字改成10就行了

 Trie_node() { //Ch_Count=0;

        hash=-1; memset(next,NULL,sizeof(next)); } }; class Trie { public: Trie(); int insert(char *word);                //插入新单词

private: Trie_node* root; }; Trie::Trie() { root = new Trie_node(); } int Trie::insert(char *word)               //边插入边查找

{ Trie_node *p = root; int len=strlen(word); if(len==0) return -1; for (int i=0;i<len;i++) { if(p->next[word[i]-'a'] == NULL)      //如果不存在的话,我们就建立一个新的节点

 { Trie_node *tmp = new Trie_node(); p->next[word[i]-'a'] = tmp; p = p->next[word[i]-'a'];         //每插入一步,相当于有一个新串经过,指针要向下移动

 } else                                //如果这个节点之前就已经存在呃,我们只需要把统计次数加上1

            p=p->next[word[i]-'a']; //p->Ch_Count++; //这里是求所有前缀出现的次数,如果只求整个单词出现次数则用后一个

 } //p->Ch_Count++; //求整个单词的出现次数



    if (p->hash<0) p->hash=words_num++; return p->hash; } Trie t; int main() { //freopen("test.in","r",stdin);

 init(); char a1[15],a2[15]; words_num=0; while(scanf("%s%s",a1,a2)!=EOF) { int x,y; x=t.insert(a1); degree[x]++; y=t.insert(a2); degree[y]++; Union(x,y); } int sum=0; for (int i=0;i<words_num;i++) { if (degree[i]%2==1) sum++; if (sum>2) { printf("Impossible\n"); return 0; } } for (int i=0;i<words_num;i++) if (Find(i)!=Find(0)) { printf("Impossible\n"); return 0; } printf("Possible\n"); return 0; }

你可能感兴趣的:(trie)