思路: hash+并查集+欧拉路
分析:
1 题目要求给定n个木棒是否可以组成一个满足要求的字符串
2 很明显的判断无向图是否是半欧拉图,首先先判断是否是单连通这一点可以利用并查集,然后在去判断是不是最多两个点的度数为奇数
3 最后一个问题就是怎么把字符串映射成整数,如果利用map肯定是超时的,那么这里就要用到hash,由于这题的数据比较弱我没有处理冲突也过了
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N = 15; const int MAXN = 500010; const int MOD = 500003; char str[N]; int cnt , father[MAXN]; int hash[MAXN] , degree[MAXN]; bool vis[MAXN]; void init(){ cnt = 1; memset(hash , 0 , sizeof(hash)); memset(degree , 0 , sizeof(degree)); memset(vis , false , sizeof(vis)); for(int i = 1 ; i < MAXN ; i++) father[i] = i; } int find(int x){ if(x != father[x]) father[x] = find(father[x]); return father[x]; } int Hash(char* s){ int sum = 0; while(*s) sum = (*s++)+(sum<<6)+(sum<<16)-sum; return (sum&0x7FFFFFFF) % MOD; } int getHash(int x){ if(!hash[x]) hash[x] = cnt++; return hash[x]; } bool isOk(){ int root; for(int i = 1 ; i <= cnt ; i++){ if(vis[i]){ root = find(i); break; } } for(int i = 1 ; i <= cnt ; i++) if(vis[i] && find(i) != root) return false; int num = 0; for(int i = 1 ; i <= cnt ; i++) if(degree[i]&1) num++; return num <= 2; } int main(){ init(); while(scanf("%s" , str) != EOF){ int x = Hash(str); x = getHash(x); scanf("%s" , str); int y = Hash(str); y = getHash(y); vis[x] = vis[y] = true; degree[x]++; degree[y]++; father[find(x)] = find(y); } if(isOk()) puts("Possible"); else puts("Impossible"); return 0; }