Problem Address:http://poj.org/problem?id=2513
【思路】
其实这道题主要是欧拉路径而不是Trie。
Trie只是相当于hash,用来表示每个颜色的编号。
以stick的左右端点为点,连线,求所成图形是否存在欧拉路径。
求欧拉路径方法:
从度数为奇数的结点出发,找到任意邻接点,将该边删除。
递归查找下去。
如果遍历所有边,则存在欧拉路径。
如果奇数度结点个数不为0或2,则不存在欧拉路径。
此外还可以用并查集的方法求。
用Trie保存结点编号。
求图是否存在欧拉路径。
注意空数据的情况。
250000sticks最多存在500000种颜色。
【代码】
#include <iostream>
using namespace std;
const int maxn = 250000;
struct node
{
node *next[26];
int index;
}trie[maxn*3];
node *root;
int total;
int degree[maxn*2+5];
int tw;
struct edge
{
int v;
int next;
}e[maxn*3];
int head[maxn*2+5];
int edgenum;
node* new_node()
{
node *p = &trie[total];
total++;
p->index = -1;
memset(p->next, NULL, sizeof(p->next));
return p;
}
int getindex(node *r, char *s)
{
int i, t;
node *p = root;
for (i=0; s[i]!='\0'; i++)
{
t = s[i] - 'a';
if (p->next[t]==NULL)
p->next[t] = new_node();
p = p->next[t];
}
if (p->index==-1)
{
p->index = tw;
tw++;
}
return p->index;
}
inline void insertEdge(int a, int b)
{
e[edgenum].v = b;
e[edgenum].next = head[a];
head[a] = edgenum;
edgenum++;
e[edgenum].v = a;
e[edgenum].next = head[b];
head[b] = edgenum;
edgenum++;
}
void find_circuit(int v)
{
int t = v;
int i, j;
if (head[v]==-1)
return;
v = e[head[v]].v;
head[t] = e[head[t]].next;
edgenum--;
i=head[v], j;
if (e[i].v==t)
{
head[v] = e[i].next;
edgenum--;
}
else
{
j = e[i].next;
while(e[j].v!=t)
{
i = j;
j = e[i].next;
}
e[i].next = e[j].next;
edgenum--;
}
find_circuit(v);
}
int main()
{
char a[15], b[15];
int ta, tb;
int i;
total = 0;
root = new_node();
tw = 0;
edgenum = 0;
memset(head, -1, sizeof(head));
memset(degree, 0, sizeof(degree));
while(scanf("%s %s", a, b)!=EOF)
{
ta = getindex(root, a);
tb = getindex(root, b);
degree[ta]++;
degree[tb]++;
insertEdge(ta, tb);
}
if (tw==0)
{
printf("Possible\n");
}
else
{
for (i=0; i<tw; i++)
{
if (degree[tw]%2==1)
break;
}
if (i<tw) find_circuit(i);
else find_circuit(0);
if (edgenum==0) printf("Possible\n");
else printf("Impossible\n");
}
return 0;
}