POJ-2513 Colored Sticks---欧拉回路+并查集+字典树

题目链接:

https://vjudge.net/problem/POJ-2513

题目大意:

给一些木棍,两端都有颜色,只有两根对应的端点颜色相同才能相接,问能不能把它们接成一根木棍

解题思路:

题意不难,典型的无向图判断是否存在欧拉通路或回路的问题。

1、欧拉通路或回路的判定条件是图联通,并且度数为奇数的点只有两个或者0个

2、颜色多,输入的字符串多,需要用字典树存储,给字符串标号用字典树标记

3、点数多,用并查集判断连通性。

第一次WA:没由开is_word标记,写成了前缀判断,此处应该是单词判断

第二次WA:判断连通的时候简单地用p[i] == i;满足该条件的数目等于1来判断连通性,但是此题输入的图可能很复杂,应该判断是否所有点的根节点是同一个点这样进行判断。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #include<set>
 7 #include<cmath>
 8 #include<algorithm>
 9 #include<vector>
10 #include<sstream>
11 #define lowbot(i) (i&(-i))
12 using namespace std;
13 
14 const int maxn = 1e6 + 10;
15 int tree[maxn][26];
16 //字典树tree[u][v]表示编号为u的节点的下一个字母为v连接的节点的编号
17 int idx(char c){ return c - 'a'; }//可以写成宏定义
18 int tot = 1;//根节点编号为1
19 bool is_word[maxn];
20 int sum[maxn];
21 int cnt = 0;//cnt
22 int Insert(char s[], int u)//u表示根节点
23 //插入字符串s
24 {
25     for(int i = 0; s[i]; i++)
26     {
27         int c = idx(s[i]);
28         if(!tree[u][c])
29             tree[u][c] = ++tot;
30         u = tree[u][c];
31     }
32     sum[u] = ++cnt;
33     is_word[u] = 1;//标记单词结尾
34     return sum[u];
35 }
36 
37 int ID(char s[], int u)//返回单词s的编号
38 {
39     for(int i = 0; s[i]; i++)
40     {
41         int c = idx(s[i]);
42         if(!tree[u][c])//还没有编号
43             return Insert(s, 1);
44         u = tree[u][c];
45     }
46     if(!is_word[u])//是前缀但是并不是单词
47     {
48         return Insert(s, 1);
49     }
50     return sum[u];
51 }
52 int p[maxn];//并查集
53 int d[maxn];//记录每个点度数之和
54 int Find(int x)
55 {
56     return x == p[x] ? x : p[x] = Find(p[x]);
57 }
58 int main()
59 {
60     for(int i = 0; i < maxn; i++)
61     {
62         p[i] = i;
63     }
64     char s1[15], s2[15];
65     int u, v, x, y;
66     while(scanf("%s%s", s1, s2) != EOF)
67     {
68         u = ID(s1, 1);
69         v = ID(s2, 1);
70         //cout<<u<<" "<<v<<endl;
71         x = Find(u);
72         y = Find(v);
73         if(x != y)p[x] = y;
74         d[u]++;
75         d[v]++;
76     }
77     int flag = 1, flag1 = 0;
78     //flag判断连通性
79     //flag1记录奇点度数的点的数目
80     int t = Find(1);
81     if(d[1] & 1)flag1++;
82     for(int i = 2; i <= cnt; i++)
83     {
84         if(Find(i) != t){flag = 0;break;}
85         if(d[i] & 1)flag1++;
86     }
87     if(flag && (flag1 == 0 || flag1 == 2))
88         printf("Possible\n");
89     else printf("Impossible\n");
90     return 0;
91 }

 

posted @ 2018-04-26 13:06  _努力努力再努力x  阅读(129)  评论(0编辑  收藏  举报