Colored Sticks
Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 32788 | Accepted: 8639 |
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
题目大意: 判断已给的棍子是否可以调整成一条直线。(前提是相接的部分是同一颜色)
思路:若要使颜色有相同的,颜色数必须为偶数。分别用两段字符串建立Tire,利用标记变量分别在建树完成后返回该颜色的建树编号。
利用此编号来记录当前颜色出现的次数,与此同时,利用并查集,看是否是连通图。判断如果颜色出现的次数为一个奇数或奇数的个数>2者直接Impossible,
否则再判断连通性,如果有颜色的跟节点不是最开始的数(在里为1),也是Impossible,否则为possible
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
#define SUM 250001
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int flag;
node *next[27];
} ;
int f[500010],cnt,s,du[500010];
char s1[16],s2[16],now[32];
node *init()
{
node *p;
p=new node ;
for(int i=0; i<26; i++)
p->next[i]=NULL;
p->flag=0;
return p;
}
int bu(node *root,char *s1)
{
int x,l;
l=strlen(s1);
for(int i=0; i<l; i++)
{
x=s1[i]-'a';
if(!root->next[x])
{
root->next[x]=init();
}
root=root->next[x];
}
if(root->flag)
return root->flag;
else
{
root->flag=++s;
return s;
}
}
int fi(int r)
{
return r==f[r]?r:f[r]=fi(f[r]);
}
void mer(int x,int y)
{
int a=fi(x);
int b=fi(y);
if(a>b)
f[a]=b;
else
f[b]=a;
}
int main()
{
s=cnt=0;
node *root;
root=new node ;
root=init();
memset(du,0,sizeof(du));
for(int i=1; i<=SUM; i++)
f[i]=i;
while(gets(now)!=NULL)//注意若是遇到这种输入的方式一定是gets()+sscanf()的形式
{
if(!strcmp(now,""))
break;
sscanf(now,"%s%s",s1,s2);
int x=bu(root,s1);
int y=bu(root,s2);//返回下标的形式,可以很好的描述du的状态,并进行连通图的判断
du[x]++;
du[y]++;
mer(x,y);
}
int tmp=0;
for(int i=1; i<=s; i++)
{
if(du[i]%2)
tmp++;
if(tmp>2)
break;
}
if(tmp%2||tmp>2)//如果是度==1||度>2则直接输出,不可能
{
puts("Impossible");
return 0;
}
bool bj=false;
for(int i=1;i<=s;i++)
{
if(f[i]!=1)//判断是不是连通图,即是否全图都是唯一的跟节点
{
bj=true;
break;
}
}
if(bj)
{
puts("Impossible");
return 0;
}
else
puts("Possible");
return 0;
}