您的位置:首页 > 其它

pku 2513 Colored Sticks

2010-04-22 16:10 197 查看
题目意思:

给出若干两端染色的木棍,两根木棍相同颜色的一端可以连在一起,问所有木棍能否连成一条

解题思路:

网上普遍的解法:字典树+并查集+欧拉通路

每输入一种颜色都让它插入到树中,并给每种颜色编号--第一个出现的颜色编号为1,第二个为2………每次输入一根木棍都将该木棍的两种颜色合并。输入完后查看是否所有的颜色的代表都一样,而且奇度点是否只出现0(欧拉回路)次或者2次。

代码:

#include <cstdio>
#include <cstring>
#define SIZE 250001

int P[SIZE]; // 代表
int R[SIZE]; // 秩
int TIME[SIZE]; // 单词出现次数
int CUR; // 现在出现的单词的个数,也是最后出现的单词的下标

struct Trie
{
Trie *next[26];
int id;
Trie():id(-1)
{
memset(next, 0, sizeof(next));
}
/* 插入,并且返回单词id */
int insert(char *s)
{
Trie *np = this;
int rs,i,j,len = strlen(s);
i = 0;
for(; i < len; ++i)
{
j = s[i] - 'a';
if (np->next[j])
np = np->next[j];
else
{
np->next[j] = new Trie();
np = np->next[j];
}
}
if (np->id==-1)
np->id = ++CUR;
rs = np->id;
return rs;
}
};

Trie T;

void link(int x, int y) // 连接(辅助合并)
{
if (R[x] > R[y])
P[x] = x;
else
{
P[x] = y;
if (R[x]==R[y])
R[x] = R[y] + 1;
}
}

int find_set(int x) // 查找
{
if (x != P[x])
P[x] = find_set(P[x]);
return P[x];
}

void enunion(int x, int y) // 合并
{
if (find_set(x) != find_set(y))
link(find_set(x), find_set(y));
}

void ini()
{
CUR = 0;
for (int i = 1; i <= SIZE - 1; ++i)
{
P[i] = i;
R[i] = 0;
TIME[i] = 0;
}
}
int isconnect() // 判断是否为连通图
{
int rep = find_set(1);
for(int i = 2; i <= CUR; ++i)
if (find_set(i)!=rep)
return 0;
return 1;
}

int count_degree() // 返回奇度点
{
int sum = 0;
for(int i = 1; i <= CUR; ++i)
sum += TIME[i]%2;
return sum;
}

int main()
{
char a[11], b[11];
int ida, idb;
ini();
while(scanf("%s%s", a, b) - EOF)
{
ida = T.insert(a);
idb = T.insert(b);
++TIME[ida];
++TIME[idb];
enunion(ida, idb);
}
int sum = count_degree();
if (isconnect() && (sum==0 || sum==2)) // 如果 是连通图 且 奇度点为2或者0
printf("Possible/n");
else
printf("Impossible/n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: