【u008】瑞瑞的木棍
2017-10-06 19:23
190 查看
Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
瑞瑞有一堆的玩具木棍,每根木棍的两端分别被染上了某种颜色,现在他突然有了一个想法,想要把这些木棍连在一起拼成一条线,并且使得木棍与木棍相接触的两端颜色都是相同的,给出每根木棍两端
的颜色,请问是否存在满足要求的排列方式。
例如,如果只有2根木棍,第一根两端的颜色分别为red,blue,第二根两端的颜色分别为red,yellow,
那么blue---red|red----yellow便是一种满足要求的排列方式。
【输入格式】
输入有若干行,每行包括两个单词,表示一根木棍两端的颜色,单词由小写字母组成,且单词长度不会超过10个字母,最多有250000根木棍。
【输出格式】
如果木棒能够按要求排列,输出Possible,否则输出Impossible
Sample Input1
blue red red violet cyan blue blue magenta magenta cyan
Sample Output1
Possible【题解】 考的是hash函数。这里我们不去构造hash函数。而用字典树的方法来实现hash。即将单词这样的字符串转换为int类型。便于我们用下标访问。然后用木棍的信息建立一张图。即一根木棍就是一条边。然后需要连接起来。它的条件就是。这整张图为欧拉图。也就是一笔画。然后判断的方法是。 1.图是联通的。 2.统计所有的点的出度。如果出度全部为偶数或者恰好只有两个点为奇数。则可以一笔画。则能够把所有的木棍都连接起来。 //联通的话用并查集也可以。用dfs从任意一个点进行搜索然后看下能不能走到所有的点。也可以。但是推荐用dfs,因为可以一边统计出度信息。 然后如果不想打字典树。还有一种方法。就是把边的信息记录下来(记录的时候,两个字符串进行一下比较,小的放前面)。然后对边的信息进行排序。以边的左端点作为关键字排序。然后左端点相同的边就会紧邻在一起。我们把字符串编号一下就可以,然后还是一样建图即可。。 【代码】
#include <cstdio> #include <cstring> struct tree//用字典树的方法来获取某个单词的hash值。 { int hash; int next[27]; }; int tot = 0, ne[500001], first[500001], en[500001], totm = 0, chudu[500001] = { 0 },temp_tot,tot_v=1; //用邻接表来存储图的信息。 bool visited[500001] = { 0 }; tree a[800001]; //用数组来模拟链表。 int sear_ch(char s[50])//用字典树。来获取s这个字符串对应的hash值。 { int l = strlen(s);//获取字符串的长度。 int p = 1;//从根节点开始往下走 for (int i = 1; i <= l; i++) { int x = s[i - 1] - 'a' + 1;//把小写字母和数字1..26对应 if (a[p].next[x] == 0)//如果这个节点不存在。则新建一个节点、 { tot_v++; a[p].next[x] = tot_v; } p = a[p].next[x];//一直往下走。 } if (a[p].hash == 0)//如果这条路径(这个字符串)之前没人走过,则给其一个新的hash值 a[p].hash = ++tot; return a[p].hash;//然后直接返回这个值就可以了。。 } void add(int x, int y)//加一条从x指向y的边 { totm++; ne[totm] = first[x];//邻接表用的是链式存储的方式。 first[x] = totm; en[totm] = y; } void dfs(int now)//这个程序会从最后一个点开始进行dfs看一下能不能走遍所有的点。 { temp_tot--;//找到了一个点,点的数目就减少。最后看temp_tot是否为0 visited[now] = true; int temp = first[now]; while (temp != 0)//用邻接表来获取这个点的出度。 { chudu[now]++;//顺便记录出度 int y = en[temp]; if (!visited[y])//如果没有访问过就访问。 dfs(y); temp = ne[temp];//寻找下一个出度 } } int main() { char s1[50], s2[50]; while (scanf("%s%s", s1, s2) != -1)//多行输入 { int x, y; x = sear_ch(s1); y = sear_ch(s2); add(x, y); add(y, x); } temp_tot = tot;//用来递减的temp if (tot>0) //如果什么都没输入也算是可以的。 dfs(tot); if (temp_tot != 0)//如果图是不连通的则不能一笔画 { printf("Impossible"); return 0; } int oushu = 0, jishu = 0;//统计奇数的出度和偶数的出度的个数。 for (int i = 1; i <= tot; i++) if ((chudu[i] % 2) == 0)//其实只要统计奇数的出度的个数就可以了。 oushu++; else jishu++; if (jishu == 0 || jishu == 2)//可以看到只要统计奇数的出度个数就可以。。 printf("Possible"); else printf("Impossible"); return 0; }
相关文章推荐
- 洛谷P1333 瑞瑞的木棍(欧拉回路)
- 洛谷.1333.瑞瑞的木棍(欧拉路径 Hash)
- 欧拉回路——洛谷 P1333 瑞瑞的木棍
- UVA 10003 切木棍
- UVA 10003 Cutting Sticks 切木棍 dp
- 【czy系列赛】czy的后宫6 && bzoj1044 [HAOI2008]木棍分割
- poj 1011/2362 dfs+剪枝(拼木棍)
- 截木棍(最大公约数)
- BZOJ1044/HAOI2008木棍分割
- BZOJ1044 [HAOI2008]木棍分割
- P1120 小木棍 [数据加强版]
- 【DFS&&搜索剪枝】CODE[VS] 3498 小木棍
- CJOJ1642 小木棍
- 【搜索】洛谷 P1120 小木棍 [数据加强版]
- 小木棍
- 洛谷—— P1120 小木棍 [数据加强版]
- uva 10003 一根木棍上有n个切割点 4000 每次选一个点切割,求总切割费用最小 区间DP
- 洛谷 P1120 小木棍[数据加强版]
- 木棍问题
- POJ 1011的一道题(木棍组合)