You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}