Colored Sticks
Description
You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a straight line such that the colors of the endpoints that touch are of the same color?
Input
Input is a sequence of lines, each line contains two words, separated by spaces, giving the colors of the endpoints of one stick. A word is a sequence of lowercase letters no longer than 10 characters. There is no more than 250000 sticks.
Output
If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.
Sample Input blue red red violet cyan blue blue magenta magenta cyan Sample Output Possible Hint
Huge input,scanf is recommended.
Source |
感想:
以为这题很水,开始写的两个代码果断TLE,后来才发现要用字典树的知识,然后又是WA,原来还要考虑输入为空的时候的情况要输出“Possible”,汗。。。!这数据,真蛋疼。还有要注意的是这题应该看做无向图。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <map>
#define maxn 500005
#define MAX 26
using namespace std;
int n,m,ans,t,num;
int sset[maxn],srank[maxn];
int in[maxn];
char s1[105],s2[105];
struct Trie //Trie结点声明
{
int isStr; //标记该结点处是否构成单词
Trie *next[MAX]; //儿子分支
};
void insert(Trie *root,const char*s) //将单词s插入到字典树中
{
if(root==NULL||*s=='\0') return;
int i;
Trie *p=root;
while(*s!='\0')
{
if(p->next[*s-'a']==NULL) //如果不存在,则建立结点
{
Trie *temp=(Trie *)malloc(sizeof(Trie));
for(i=0; i<MAX; i++)
{
temp->next[i]=NULL;
}
temp->isStr=0;
p->next[*s-'a']=temp;
p=p->next[*s-'a'];
}
else
{
p=p->next[*s-'a'];
}
s++;
}
p->isStr=++t; //单词结束的地方标记此处可以构成一个单词
}
int search(Trie *root,const char*s) //查找某个单词是否已经存在
{
Trie *p=root;
while(p!=NULL&&*s!='\0')
{
p=p->next[*s-'a'];
s++;
}
if(p!=NULL&&p->isStr!=0) return p->isStr; //在单词结束处的标记为true时,单词才存在
return 0;
}
void del(Trie *root) //释放整个字典树占的堆区空间
{
int i;
for(i=0; i<MAX; i++)
{
if(root->next[i]!=NULL)
{
del(root->next[i]);
}
}
free(root);
}
void init()
{
int i;
for(i=0; i<maxn; i++)
{
sset[i]=i;
srank[i]=1;
}
num=0;
}
int sfind(int x) // 查找时优化了路径
{
int r=x,nn;
while(sset[r]!=r) r=sset[r];
while(x!=r)
{
nn=sset[x];
sset[x]=r;
x=nn;
}
return r;
}
void smerge(int a,int b) // 合并时将深度小的集合合并到大的里面
{
int x,y;
x=sfind(a);
y=sfind(b);
if(x!=y)
{
if(srank[x]<srank[y]) sset[x]=y;
else
{
sset[y]=x;
if(srank[x]==srank[y]) srank[x]++;
}
num++;
}
}
bool solve()
{
int i,j,u,h;
u=0;
if(num!=t-1) return false ;
for(i=1;i<=t;i++)
{
if(in[i]&1) u++;
}
if(u==0||u==2) return true ;
return false ;
}
int main()
{
int i,j,x,y;
t=0;
init();
Trie *root= (Trie *)malloc(sizeof(Trie));
for(i=0; i<MAX; i++)
{
root->next[i]=NULL;
}
root->isStr=0;
memset(in,0,sizeof(in));
while(~scanf("%s%s",s1,s2))
{
x=search(root,s1);
if(!x) // 不存在就建立
{
insert(root,s1);
x=t;
}
y=search(root,s2);
if(!y)
{
insert(root,s2);
y=t;
}
in[x]++;
in[y]++;
smerge(x,y);
}
if(t==0)
{
printf("Possible\n");
return 0;
}
if(solve()) printf("Possible\n");
else printf("Impossible\n");
// del(root);
return 0;
}