给你N个棍子,每个棍子的两端涂有颜色。两个涂有一种颜色的端点可连在一起。
问这N根棍子是否能连成一条直线。
可以把每个棍子看成一条边,端点为两个节点。则问题转化成所给的这些端点是否连通,若连通是否存在一笔画的问题,即是否存在欧拉回路。
并查集+路径压缩 判断图是否连通。
另在图连通的情况下若不存在度数为奇数的点或有且仅有两个度数为奇数的点,则存在欧拉回路。
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdio>
4 #include <algorithm>
5 #include <cstring>
6
7 using namespace std;
8
9 int me[510000];
10 int degree[510000] = {0};
11 int ans_color;
12
13 struct Tire
14 {
15 Tire *next[26];
16 int ans;
17 }*root;
18
19 Tire *creat()
20 {
21 Tire * p = (Tire *)malloc(sizeof(Tire));
22 for(int i = 0;i < 26; i++)
23 p->next[i] = NULL;
24 p->ans = -1;
25 return p;
26 }
27
28 int ans_odd,ans_sum;
29
30 int insert(Tire *root,char *s)
31 {
32 int len = 0;
33 while(s[len] != '\0')
34 {
35 if(root->next[s[len]-'a'] == NULL)
36 root->next[s[len]-'a'] = creat();
37 root = root->next[s[len]-'a'];
38 ++len;
39 }
40 if(root->ans == -1)
41 root->ans = ans_sum++;
42 return root->ans;
43 }
44
45 int find(int x)
46 {
47 int j,k,r;
48 r = x;
49 while(r != me[r])
50 r = me[r];
51 k = x;
52 while(k != r)
53 {
54 j = me[k];
55 me[k] = r;
56 k = j;
57 }
58 return r;
59 }
60
61 void merge(int u,int v)
62 {
63 int fu = find(u);
64 int fv = find(v);
65
66 me[fv] = fu;
67 return ;
68 }
69
70 int main()
71 {
72 char s1[11],s2[11];
73
74 root = creat();
75
76 int i,sum;
77
78 int u,v;
79
80 for(i = 0;i <= 510000; ++i)
81 me[i] = i;
82
83 ans_odd = 0;
84 ans_sum = 0;
85
86 while(scanf("%s %s",s1,s2) != EOF)
87 {
88 u = insert(root,s1);
89 v = insert(root,s2);
90 degree[u]++;
91 degree[v]++;
92 merge(u,v);
93 }
94
95 int pa = find(0);
96
97 for(ans_odd = 0,i = 0,sum = 0;i < ans_sum; i++)
98 {
99 if( (degree[i]&1) == 1)
100 ans_odd++;
101
102 if(me[i] == i)
103 ++sum;
104
105 if(ans_odd > 2 || sum > 1)
106 {
107 printf("Impossible\n");
108 return 0;
109 }
110 }
111
112 if(ans_sum != 1)
113 printf("Possible\n");
114 else
115 printf("Impossible\n");
116
117 return 0;
118 }