POJ 2513 Colored Sticks (Trie字典树+欧拉通路+并查集) 解题报告

来源:互联网 发布:计算机加密软件 编辑:程序博客网 时间:2024/05/17 02:36

题意:

       有n根棍子,n<=250000,每根棍子两端各有一种颜色,如果两根棍子各有一个端点颜色相同,则可以把这两个端点连起来从而把这两个棍子连成线。现在给出每根棍子两端的颜色,问能否把所有棍子连成一条线。

思路:

       首先,可以想到以颜色为顶点,棍子为边构图,则所有棍子能连成线等同于该图中存在欧拉通路。回忆一下欧拉通路的充要条件:(1)该图连通;(2)度数为奇数的顶点数为0或者2。其中条件(1)经常被粗心忽略掉,其实条件(1)才是最根本的条件。

       接下来,问题就是对字符串的处理了。10个长度的字符串直接hash会爆内存,我采用的是字典树存储id值,新增一个颜色时,先在字典树中查找有没有,如果有,直接使用其id值,如果没有,在字典树中新增,总id值加1。这样一来,就可以转化为对于整数的处理问题了。     

       连通性用并查集判断,再记录每个顶点的度,就能判断是否存在欧拉通路。

       最后,这道题存在空数据,空数据要输出Possible,这个trick要注意下。

代码:

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int MAXA = 26;//可能出现的字符种类数,如果只有小写字母就是26种const int MAXL = 12;//单词的最长长度const int MAXN = 500010;int degree[MAXN];int father[MAXN];struct Node{bool is_str;//标记该节点处是否构成单词int id;//该单词的myhash值Node* nxt[MAXA];//儿子分支};int color;//当前的颜色数目,用与分配myhash值void insert(Node *rt, const char *s){if (rt == NULL || *s == 0)return;int i;Node *p = rt;while (*s != 0){if (p->nxt[*s-'a'] == NULL){Node *tmp = new Node;for (i = 0; i < MAXA; ++i)tmp->nxt[i] = NULL;tmp->is_str = false;p->nxt[*s-'a'] = tmp;p = p->nxt[*s-'a'];}elsep = p->nxt[*s-'a'];++s;}father[color] = color;p->id = color++;p->is_str = true;}int myhash(Node *rt, const char *s){Node *p = rt;char t[MAXL];strcpy(t,s);while (p != NULL && *s != 0){p = p->nxt[*s-'a'];++s;}if (p != NULL && p->is_str == true)return p->id;else{insert(rt,t);return color-1;}}int find(int x){if (father[x] != x)return x = find(father[x]);elsereturn x;}void union_set(int x,int y){int px = find(x);int py = find(y);if (px != py)father[py] = px;}bool in_one_set(int x,int y){return (find(x) == find(y));}void del(Node *rt){int i;for (i = 0; i < MAXA; ++i){if (rt->nxt[i] != NULL)del(rt->nxt[i]);}free(rt);}int main(){int i;char s[MAXL],t[MAXL];//初始化字典树Node *rt = new Node;for (i = 0; i < MAXA; ++i)rt->nxt[i] = NULL;rt->is_str = false;memset(degree,0,sizeof(degree));color = 0;while (scanf("%s %s",s,t) != EOF){int a = myhash(rt,s);int b = myhash(rt,t);++degree[a];++degree[b];union_set(a,b);}int res = 0;for (i = 0; i < color; ++i){if (degree[i] % 2 == 1)++res;}if (color == 0)printf("Possible\n");else if (res == 0 || res == 2){bool flag = false;for (i = 0; i < color-1; ++i){if (in_one_set(i,i+1) == false)flag = true;}if (flag)printf("Impossible\n");elseprintf("Possible\n");}elseprintf("Impossible\n");del(rt);return 0;}


0 0
原创粉丝点击