这道题就是判断一笔画问题
建图的时候以颜色为点,棍子边为边。
先判断是否连通,再判断odd点的个数,个数不超过2即可。
注意这里颜色都是用字符串来表示的,我一开始用string的二分查找树,每次查询复杂度是 O(klongn) ,k 是字符串长度。trie的话是 O(k),用前面的T了,trie的话速度还不错300+MS
这个代码中并查集和trie写在一块儿了,真是麻烦,应该都封装起来的。
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <map>
#include <assert.h>
#include <string>
using namespace std;
#define MAX 600000
int cnt;
struct node
{
int cnt;
int color;
node *next[26];
}Trie;
int mem;
node memAlloc[MAX];
map<string,int> mpsi;
map<int,int> mpii;
node* create()
{
return &memAlloc[mem++];
}
int insert(char c[30])
{
node *p=&Trie;
for(int i=0;c[i]!='\0';i++)
{
if(!p->next[c[i]-'a'])
p->next[c[i]-'a']=create();
p=p->next[c[i]-'a'];
}
if(!p->color)
p->color=++cnt;
p->cnt++;
return p->color;
}
int odd;
void trival(node * p)
{
if(!p)
return ;
if(p->color&&p->cnt%2)
odd++;
for(int i=0;i<26;i++)
trival(p->next[i]);
}
int pre[MAX];
void init()
{
for(int i=0;i<MAX;i++)
pre[i]=i;
}
int find(int x)
{
return x==pre[x]?x:pre[x]=find(pre[x]);
}
void join(int x,int y)
{
pre[find(x)]=pre[find(y)];
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main()
{
freopen("acm.in","r",stdin);
init();
char f[30],t[30];
for(int i=0;scanf("%s%s",f,t)!=EOF;i++)
{
int a=insert(f);
int b=insert(t);
join(a,b);
}
int rt=find(1);
for(int i=1;i<=cnt;i++)
if(find(i)!=rt)
{
puts("Impossible");
return 0;
}
trival(&Trie);
if(odd>2)
puts("Impossible");
else
puts("Possible");
return 0;
}