POJ-2513 Colored Sticks 无向图欧拉通路判定+字符串hash
题意:给定许多根棍子,这些棍子两头有不同的颜色,问是否能够存在这样一中组合方式使得所有的棍子首尾相连。
解法:这题使用map处理字符串超时了,所以自己写了一个插值取模的字符串hash。只要判定图是否连通和度为奇数是否大于2个即可,不可能出现奇数个度为奇数的点。
代码如下:
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> #include <map> #include <string> #include <vector> using std::vector; typedef unsigned long long int64; const int MOD = 250007; const int64 T = 37; char sa[15], sb[15]; int deg[500005]; int set[500005]; int head[250010]; int64 _pow[15]; vector<int>v; struct Edge { int tag, next; int64 key; }e[500005]; int idx, tag; int find(int x) { return set[x] = x == set[x] ? x : find(set[x]); } void merge(int a, int b) { set[a] = b; } void insert(int64 key, int tg) { int pos = key % MOD; e[idx].key = key; e[idx].tag = tg; e[idx].next = head[pos]; head[pos] = idx++; } int64 getkey(char str[]) { int64 key = 0; int len = strlen(str); for (int i = 0; i < len; ++i) { key += (str[i]-'a') * _pow[i]; } return key; } void hash(char str[]) { int64 key = getkey(str); insert(key, tag++); } int get(char str[]) { int64 key = getkey(str); int pos = key % MOD; for (int i = head[pos]; i != -1; i = e[i].next) { if (e[i].key == key) { return e[i].tag; } } return -1; } int main() { int ok = 0; for (int i = 0; i < 500000; ++i) { set[i] = i; } _pow[0] = 1; for (int i = 1; i <= 10; ++i) { _pow[i] = T * _pow[i-1]; } memset(head, 0xff, sizeof (head)); while (scanf("%s %s", sa, sb) != EOF) { if (get(sa) == -1) { hash(sa); } if (get(sb) == -1) { hash(sb); } int a = get(sa), b = get(sb); ++deg[a], ++deg[b]; merge(find(a), find(b)); } for (int i = 0; i < tag; ++i) { if (set[i] == i) { ++ok; } if (deg[i] & 1) { v.push_back(i); } } if (ok != 1 && ok) { puts("Impossible"); return 0; } else if (v.size() > 2){ puts("Impossible"); } else { puts("Possible"); } return 0; }