思路:把每根筷子的两个端点的字符串看成一个点,建图,问题即转化为判断图是否是含有欧拉通路,满足两个条件:
(1)图是连通图,(2)奇数度的点个数要么是0,要么是2。
无向图判断是否连通很简单,并查集直接搞就行,最后看是不是只有一个连通分量。
建图时把每个字符串转化为一个整数,这样才好建图,第一反应是用map,交了一发TLE,然后干脆直接用trie树吧,1000+ms过的,有点慢。
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 250010;
typedef struct Node{
int cnt;
Node *child[26];
Node(){
cnt = 0;
for(int i = 0;i < 26;i ++)
child[i] = NULL;
}
}Node;
Node* root;
int father[(MAXN << 1)+10],ind[(MAXN << 1)+10],n;
inline int update(char* str){
Node *tmp = root;
while(*str != '\0'){
if(tmp->child[*str-'a'] == NULL){
Node *p = new Node();
tmp->child[*str-'a'] = p;
}
tmp = tmp->child[*str-'a'];
str++;
}
if(tmp->cnt == 0) tmp->cnt = ++n;
return tmp->cnt;
}
inline void init(){
n = 0,root = new Node();
memset(ind,0,sizeof ind);
for(int i = 1;i <= MAXN*2;i ++)
father[i] = i;
}
int find(int x){
return x == father[x] ? x : father[x] = find(father[x]);
}
inline void merge(int x,int y){
x = find(x);
y = find(y);
father[y] = x;
}
int main(){
init();
int x,y;
char str1[20],str2[20];
#ifndef ONLINE_JUDGE
freopen("in.cpp","r",stdin);
#endif
while(~scanf("%s%s",str1,str2)){
x = update(str1),y = update(str2);
if(find(x) != find(y)) merge(x,y);
ind[x]++,ind[y]++;
}
int sum = 0;
for(int i = 1;i <= n;i ++){
if(i == find(i)) sum ++;
if(sum > 1){
printf("Impossible\n");
return 0;
}
}
sum = 0;
for(int i = 1;i <= n;i ++){
if(ind[i]&1) sum ++;
if(sum > 2){
printf("Impossible\n");
return 0;
}
}
printf("Possible\n");
return 0;
}