题目:http://poj.org/problem?id=2513
两个教训:
一、输入输出用scanf、printf(好像自己已经强调很多遍了= =……)
eg:用cin 1000MS 用scanf 400MS…………
二、不要把string作为函数值传递参数(推广到整个STL,STL加了很多没用的功能会导致效率变低)
eg:此题Trie中的参数用string 4485MS 用char * 985MS…………
/*
题目大意:每个木棒头尾都有两种颜色,木棒末端颜色相同的可以连接成一条直线,问能否将所有木棒连接起来组成一条直线。
题目求解:传换成图的问题就是求解能否一笔画成(欧拉通路)
代码技巧:用数组字典树和链表字典树都可以,动态链表空间少好写,静态数组速度快,看情况吧。
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <climits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
#define N 500005
struct set
{
int parent; //记录父节点
int rank; //记录集合的节点数
}elem[N];
int MAX;
void init()
{
int i;
for(i=0;i<=N;i++)
{
elem[i].parent=i;
elem[i].rank=1;
}
}
int Find(int x)
{
int root,temp;
temp=x;
while(x!=elem[x].parent) //寻找根节点
x=elem[x].parent;
root=x;
x=temp;
while (x!=elem[x].parent) //压缩路径,全部赋值为根节点的值
{
temp=elem[x].parent;
elem[x].parent=root;
x=temp;
}
return root;
}
void Union(int a,int b) //合并两个集合
{
int x,y;
x=Find(a);
y=Find(b);
if(elem[x].rank>=elem[y].rank)
{
elem[y].parent=elem[x].parent;
elem[x].rank+=elem[y].rank;
if(MAX<elem[x].rank)
MAX=elem[x].rank;
}
else
{
elem[x].parent=elem[y].parent;
elem[y].rank+=elem[x].rank;
if(MAX<elem[y].rank)
MAX=elem[y].rank;
}
}
//Trie树模板 by AbandonZHANG
int words_num;
int degree[500005];
struct Trie_node
{
//int Ch_Count; //统计单词个数,如果为0表示没有该串。
int hash; //单词hash后的标识数
Trie_node *next[26];//指向各个子树的指针,下标0-25代表26字符,如果是数字改成10就行了
Trie_node()
{
//Ch_Count=0;
hash=-1;
memset(next,NULL,sizeof(next));
}
};
class Trie
{
public:
Trie();
int insert(char *word); //插入新单词
private:
Trie_node* root;
};
Trie::Trie()
{
root = new Trie_node();
}
int Trie::insert(char *word) //边插入边查找
{
Trie_node *p = root;
int len=strlen(word);
if(len==0) return -1;
for (int i=0;i<len;i++)
{
if(p->next[word[i]-'a'] == NULL) //如果不存在的话,我们就建立一个新的节点
{
Trie_node *tmp = new Trie_node();
p->next[word[i]-'a'] = tmp;
p = p->next[word[i]-'a']; //每插入一步,相当于有一个新串经过,指针要向下移动
}
else //如果这个节点之前就已经存在呃,我们只需要把统计次数加上1
p=p->next[word[i]-'a'];
//p->Ch_Count++; //这里是求所有前缀出现的次数,如果只求整个单词出现次数则用后一个
}
//p->Ch_Count++; //求整个单词的出现次数
if (p->hash<0)
p->hash=words_num++;
return p->hash;
}
Trie t;
int main()
{
//freopen("test.in","r",stdin);
init();
char a1[15],a2[15];
words_num=0;
while(scanf("%s%s",a1,a2)!=EOF)
{
int x,y;
x=t.insert(a1);
degree[x]++;
y=t.insert(a2);
degree[y]++;
Union(x,y);
}
int sum=0;
for (int i=0;i<words_num;i++)
{
if (degree[i]%2==1)
sum++;
if (sum>2)
{
printf("Impossible\n");
return 0;
}
}
for (int i=0;i<words_num;i++)
if (Find(i)!=Find(0))
{
printf("Impossible\n");
return 0;
}
printf("Possible\n");
return 0;
}