Description:
给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。
解题思路:
可以用图论中欧拉路的知识来解这道题,首先可以把木棒两端看成节点,把木棒看成边,这样相同的颜色就是同一个节点
问题便转化为:
给定一个图,是否存在“一笔画”经过涂中每一点,以及经过每一边一次。
这样就是求图中是否存在欧拉路Euler-Path。(我才知道这个就是欧拉路径。。。T_T)
由图论知识可以知道,无向图存在欧拉路的充要条件为:
① 图是连通的; // 用并查集判断就好啦。
② 所有节点的度为偶数,或者有且只有两个度为奇数的节点。
附代码(虽然有点小疑问):
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<string>
#define maxn 500000 + 100
using namespace std;
int fa[maxn];
int du[maxn];
int cnt;
void init()
{
int i;
for (i=0; i<maxn; ++i)
{
fa[i] = i;
}
cnt = 0;
}
int find(int v)
{
if (fa[v] == v) return v;
return fa[v] = find(fa[v]);
}
void unin(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
fa[fx] = fy;
}
struct trie
{
trie *next[26];
int key;
bool isleaf;
trie()
{
for (int i=0; i<26; ++i)
{
next[i] = NULL;
}
key = 0;
isleaf = false;
}
}Root, Node;
int creatTree(char word[])
{
trie *p = &Root;
char *str = word;
while(*str)
{
if (p->next[*str-'a'] == NULL)
p->next[*str-'a'] = new trie;
p = p->next[*str-'a'];
str++;
}
if (p->isleaf)
return p->key;
else
{
p->isleaf = true;
p->key = cnt++;
return p->key;
}
}
int main()
{
char str1[20], str2[20];
init();
while(~scanf("%s%s", str1, str2))
{
int a, b;
a = creatTree(str1);
b = creatTree(str2);
du[a]++; // T_T 还是布吉岛为什么。如果这两种颜色已经属于一个集合了。为什么还要度数++呢。所以。额。
du[b]++;
if (find(a) != find(b))
{
// du[a]++;
// du[b]++;
unin(a, b);
}
}
int temp = 0;
for (int i=0; i<cnt; ++i)
{
if (du[i] % 2)
temp++;
}
if (temp != 0 && temp != 2)
{
printf("Impossible\n");
return 0;
}
int ttemp = find(0);
for (int i=1; i<cnt; ++i)
{
if (find(i) != ttemp)
{
printf("Impossible\n");
return 0;
}
}
printf("Possible\n");
return 0;
}