题目地址:POJ 2513
刚开始没想到字典树,用的map函数一直TLE,由于上一次的签到题由于没想到字典树而卡了好长时间的深刻教训,于是过了不久就想起来用字典树了,(为什么是在TLE了5次之后。。T^T)然后把map改成了字典树,然后就过了。
这题居然不知不觉的用上了欧拉回路。。其实当时我是这样想的。。因为相互接触的必须要相同,所以除了两端外,其他的都是两两相同的,所以除了两端的颜色外其他的的个数必须为偶数。然后两端的可能相同可能不相同,相同的话,说明所有的都是偶数个数了,不相同的话那就只有这两个颜色个数为奇数。也就是判断保证连通性的同时,只要再保证颜色的个数为奇数的只有0个或两个,由于总个数为偶数,所以这里只要有一个奇数,那肯定还有一个奇数的,不可能存在1个奇数的情况,所以只需要判断是否大于2就行了。赛后才知道原来这就叫欧拉回路。。= = !
代码如下:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include<algorithm>
using namespace std;
int d[500000], cnt, n, bin[500000];
struct node
{
int flag;
node *next[30];
};
node T[5000000];
node *newnode()
{
int i;
node *p=&T[cnt++];
for(i=0;i<26;i++)
{
p->next[i]=NULL;
}
p->flag=0;
return p;
}
int charu(node *root, char *s)
{
int i, x, len=strlen(s);
node *p=root;
for(i=0;i<len;i++)
{
x=s[i]-'a';
if(p->next[x]==NULL)
{
p->next[x]=newnode();
}
p=p->next[x];
}
if(p->flag)
return p->flag;
else
{
p->flag=++n;
return n;
}
}
int find1(int x)
{
return bin[x]==x?x:bin[x]=find1(bin[x]);
}
void merger(int x, int y)
{
int f1=find1(bin[x]);
int f2=find1(bin[y]);
if(f1!=f2)
{
if(f2>f1)
bin[f2]=f1;
else
bin[f1]=f2;
}
}
int main()
{
int i, j, s=0, x=0, x1, x2;
char s1[11], s2[11];
memset(d,0,sizeof(d));
for(i=1;i<=500000;i++)
{
bin[i]=i;
}
n=0;
cnt=0;
node *root;
root=newnode();
while(scanf("%s%s",s1,s2)!=EOF)
{
x1=charu(root,s1);
x2=charu(root,s2);
d[x1]++;
d[x2]++;
merger(x1,x2);
//printf("%d %d\n",x1,x2);
}
for(i=1;i<=n;i++)
{
if(d[i]%2)
s++;
if(s>2)
{
x=1;
break;
}
}
if(x)
printf("Impossible\n");
else
{
int y=0;
for(i=1;i<=n;i++)
{
if(find1(bin[i])!=1)
{
y=1;
break;
}
}
if(y)
printf("Impossible\n");
else
printf("Possible\n");
}
return 0;
}