72 lines
2.5 KiB
C++
72 lines
2.5 KiB
C++
#include <iostream>
|
||
#include <cstdio>
|
||
#include <algorithm>
|
||
#include <map>
|
||
#include <cstring>
|
||
using namespace std;
|
||
|
||
const int N = 250010 << 1;
|
||
int p[N]; // 并查集
|
||
int d[N]; // 度
|
||
|
||
/*
|
||
在这个代码中,我们定义了一个函数getHash来获取字符串的哈希值。
|
||
这个函数使用了一种称为多项式滚动哈希的方法,它将字符串看作一个131进制的数,并将每个字符的ASCII值减去'a'的ASCII值
|
||
加1作为该字符的值。然后,我们将每个字符的值乘以31的相应次方,并将结果加到哈希值上。
|
||
为了防止哈希值溢出,我们在每一步都对哈希值取模N。
|
||
*/
|
||
int getHash(string s) {
|
||
int P = 131, b = 1, hash = 0;
|
||
for (int i = 0; i < s.size(); i++) {
|
||
hash = (hash + s[i] * b) % N;
|
||
b = (b * P) % N;
|
||
}
|
||
return hash;
|
||
}
|
||
|
||
// 并查集
|
||
int find(int x) {
|
||
if (x == p[x]) return x;
|
||
return p[x] = find(p[x]);
|
||
}
|
||
|
||
char str1[15], str2[15]; // 两个字符串
|
||
int b[N]; // 判断某个字符串HASH值是不是已经出现过的桶
|
||
|
||
int main() {
|
||
#ifndef ONLINE_JUDGE
|
||
freopen("POJ2513.in", "r", stdin);
|
||
#endif
|
||
// 初始化并查集
|
||
for (int i = 0; i < N; i++) p[i] = i;
|
||
// 离散化后的节点编号,是不是存在一笔画的标识
|
||
int id = 0, flag = 1;
|
||
|
||
while (~scanf("%s%s", str1, str2)) {
|
||
int s1 = getHash(str1), s2 = getHash(str2); // 计算出个字符串的HASH值,而且,数值在N以下,这样才能用桶
|
||
if (!b[s1]) b[s1] = ++id; // 给字符串编号,去重
|
||
if (!b[s2]) b[s2] = ++id; // 给字符串编号,去重
|
||
int x = b[s1], y = b[s2]; // 去重+映射后的字符串编号
|
||
d[x]++, d[y]++; // 记录度
|
||
// 合并并查集
|
||
if (find(x) != find(y)) p[find(x)] = find(y); // 辅助校验图是否是连通的
|
||
}
|
||
|
||
int odd = 0, cnt = 0;
|
||
for (int i = 1; i <= id; i++) { // 枚举每个去重后的字符串
|
||
if (p[i] == i) cnt++; // 连通块个数
|
||
if (d[i] % 2) odd++; // 奇数度节点个数
|
||
}
|
||
|
||
// 如果奇数度个数不是0,而且,还不是2,那肯定不是一笔画
|
||
// 如果连通块个数不是1,也不能一笔画
|
||
if ((odd != 0 && odd != 2) || cnt != 1) flag = 0;
|
||
// 空数据也需要处理,这太BT了!
|
||
if (id == 0) flag = 1;
|
||
|
||
if (flag)
|
||
puts("Possible");
|
||
else
|
||
puts("Impossible");
|
||
return 0;
|
||
} |