Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 38355 | Accepted: 10044 |
Description
Input
Output
Sample Input
blue red
red violet
cyan blue
blue magenta
magenta cyan
Sample Output
Possible
Hint
Source
题意:
给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。
解题思路:
将每一根火柴棍,看成一条边,相同的颜色为同一个点,这样我们可以把原问题转化为,是否可以画一条线,经过所有边一次且仅一次。这就是欧拉图,问是否存在欧拉通路(或者欧拉回路也可以)。
欧拉通路也叫半欧拉图,欧拉回路也叫欧拉图。
无向图G是半欧拉图 当且仅当 1.G是连通的 2.恰有两个奇度定点
无向图G是欧拉图 当且仅当 1.G是连通的 2.没有奇度定点
ps:或许与人会注意到,每次插入的是一条边,每条边上有两个点,那么是否可以这样想:如果有两条边有颜色相同的点,那么就把这两个点粘起来,形成一条新边,这样一直插入所有边,如果木棍能够连接成一条直线,那么最后应该只剩下两个端点,如果大于两个端点,就不能连成一条直线。因为每次输入的是一条边,所以输入的两个点一定是连通的,将它与另一个边相接,新生成的木棍一定也是连通的,所以这种不像是判断欧拉图那样一个点一个点的输入,是否可以不判断连通性?答案是不可以,因为木棍可能两端点同色,这样,木棍在我们的模拟中,就会退化成一个点,所以这个问题又退化成了单点输入的欧拉图问题。
所以我们首先判断奇度定点的个数。将颜色string与出现次数int联系起来
如果使用map的话会超时,虽然STL的map是基于hash的基础上,但并不高效
这里使用字典树为每个字符串一个编号。
关于字典树=》浅谈Trie树(字典树)
判断是否联通肯定就是用并查集了。使用并查集时必须压缩路径,前几次搜索某个结点k的祖先时,在不断通过父亲结点寻找祖先结点时,顺便把从k到最终祖先结点S中经过的所有结点的祖先都指向S,那么以后的搜索就能把时间降低到O(1)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 const int large = 250000*2;//最多有250000*2个结点 6 int color=0;//记录当前颜色的编号 7 int Count[large+1] = {0};//第id个结点出现的次数 8 int ancestor[large+1];//第id个结点的祖先 9 10 class HashTable{ 11 public: 12 int id; 13 HashTable *next[27];//存储子树的颜色 14 HashTable()//初始化 15 { 16 id = 0; 17 memset(next,0,sizeof(next)); 18 } 19 }root;//根节点root 20 21 int hash(char *a) 22 { 23 HashTable *temp = &root;//从根节点开始查找 24 int i=0; 25 while(a[i] != '