Colored Sticks
Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 30063 | Accepted: 7933 |
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.
这个题数据非常的大,所以要用字典树来统计单词的个数,然后放到哈希表中,用并查集把他们连接起来,如果能连接成一条线,就是可能的,如果不能,就不可能,是否能连接成一条线,用欧拉图的判定方式...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
int no;
struct node *next[26];
}*head;//字典树的头
int hs[500010];//哈希数组
int s[500010];
int num=0;
int nfind(int x)//并查集的查找函数
{
int r=x,q;
while(x!=s[x])
{
x=s[x];
}
while(s[r]!=x)
{
q=s[r];
s[r]=x;
r=q;
}
return x;
}
void cz(int x,int y)//调用查找函数(并查集的一部分)
{
int fx=nfind(x);
int fy=nfind(y);
if(fx!=fy)
s[fx]=fy;
}
int creat(char sr[])//字典树的建立
{
int l,i,zh,j;
struct node *p,*r;
p=head;
l=strlen(sr);
for(i=0;i<l;i++)
{
zh=sr[i]-'a';
if(p->next[zh]==NULL)
{
r=(struct node *)malloc(sizeof(struct node));
for(j=0;j<26;j++)
{
r->next[j]=NULL;
}
r->no=0;
p->next[zh]=r;
p=p->next[zh];
}
else
{
p=p->next[zh];
}
}
if(p->no==0)
{
num++;
p->no=num;//为每一个单词自己定义一个编号,用哈希来记录个数
}
return p->no;
}
int main()
{
char sr1[11],sr2[11];
int x,y,i,js=0,flag=0,bj;
head=(struct node *)malloc(sizeof(struct node));
for(i=0;i<26;i++)
{
head->next[i]=NULL;
}
memset(hs,0,sizeof(hs));
for(i=0;i<=500000;i++)
{
s[i]=i;//并查集的数组初始化
}
while(~scanf("%s%s",sr1,sr2))
{
x=creat(sr1);
y=creat(sr2);
hs[x]++;
hs[y]++;//用哈希统计入度和出度
cz(x,y);//让两个编号连通(因为他们是一根棍,必然连通)
}
for(i=1;i<=num;i++)
{
if(hs[i]%2==1)//统计入度和出度
{
js++;
if(js>2)//如果出度和入度的和大于2,则构不成欧拉图
{
flag=1;
break;
}
}
}
bj=nfind(1);
for(i=2;i<=num;i++)//看看是否是一个能连通的棍
{
if(nfind(i)!=bj)
{
flag=1;
break;
}
}
if(!flag&&(js==0||js==2))//如果入度和出度为0或2,并且是一个连通的棍
{
printf("Possible\n");
}
else
{
printf("Impossible\n");
}
return 0;
}
Source
其实还有一种方法:根据欧拉图的定义来判定
#include <stdio.h>
#include <string.h>
struct node
{
int flag;
struct node *next[26];
}*head;
int num = 1;
int rd[500010];
int cd[500010];
int bcj[500010];
int creat(char *s,int n)
{
int l = strlen(s);
int zh;
node *p;
p = head;
for(int i = 0; i < l; i++)
{
zh = s[i] - 'a';
if(p->next[zh] == NULL)
{
node *q = new node;
for(int j = 0; j < 26; j++)
{
q->next[j] = NULL;
}
q->flag = 0;
p->next[zh] = q;
p = q;
}
else
{
p = p->next[zh];
}
}
if(p->flag == 0)
{
p->flag = num++;
}
if(n == 1)
{
cd[p->flag]++;
}
else
{
rd[p->flag]++;
}
return p->flag;
}
int nfind(int x)
{
int r = x,q;
while(bcj[x] != x)
x = bcj[x];
while(bcj[r] != x)
{
q = bcj[r];
bcj[r] = x;
r = q;
}
return x;
}
void lj(int x,int y)
{
int fx = nfind(x);
int fy = nfind(y);
if(fx != fy)
bcj[fx] = fy;
}
int main()
{
int flag = 1;
char s1[15],s2[15];
head = new node;
for(int i = 0; i < 26; i++)
{
head->next[i] = NULL;
}
for(int i = 0; i <= 500000; i++)
{
bcj[i] = i;
}
memset(rd,0,sizeof(rd));
memset(cd,0,sizeof(cd));
while(~scanf("%s%s",s1,s2))
{
int x = creat(s1,1);
int y = creat(s2,2);
lj(x,y);
}
int cs = 0;
int rs = 0;
int sy = 0;
int gs = 0;
for(int i = 1; i < num; i++)
{
if((cd[i] || rd[i]) && (bcj[i] == i))
{
gs++;
if(gs > 1)
{
printf("Impossible\n");
// printf("gs = %d\n",gs);
flag = 0;
break;
}
}
if(rd[i] - cd[i] == 1)
{
rs++;
}
else if(cd[i] - rd[i] == 1)
{
cs++;
}
else
{
sy++;
}
}
if(flag)
{
// printf("rs = %d cs = %d sy = %d num = %d\n",rs,cs,sy,num);
if((rs == 1 && cs == 1 && (rs + cs + sy == num - 1)) || (rs == 0 && cs == 0 && (rs + cs + sy == num - 1)))
{
printf("Possible\n");
}
else
{
printf("Impossible\n");
}
}
return 0;
}
我自己的写的:真正知道了什么叫欧拉路,什么叫欧拉回路
#include <stdio.h>
#include <string.h>
struct node
{
int flag;
node *next[26];
}*head;
int rd[500010];
int cd[500010];
int s[500010];
int num = 1;
int creat(char *str)
{
int zh,len = strlen(str);
node *p = head;
for(int i = 0;i < len;i++)
{
zh = str[i] - 'a';
if(p->next[zh] == NULL)
{
node *q = new node;
for(int j = 0;j < 26;j++)
{
q->next[j] = NULL;
}
q->flag = 0;
p->next[zh] = q;
}
p = p->next[zh];
}
if(p->flag == 0)
p->flag = num++;
return p->flag;
}
int nfind(int x)
{
int r = x,q;
while(s[x] != x)
x = s[x];
while(s[r] != x)
{
q = s[r];
s[r] = x;
r = q;
}
return x;
}
void lj(int x,int y)
{
int fx = nfind(x);
int fy = nfind(y);
if(fx != fy)
s[fx] = fy;
}
int main()
{
char str1[15],str2[15];
head = new node;
for(int i = 0;i < 26;i++)
head->next[i] = NULL;
memset(rd,0,sizeof(rd));
memset(cd,0,sizeof(cd));
for(int i = 1;i <= 500010;i++)
s[i] = i;
while(~scanf("%s%s",str1,str2))
{
int x = creat(str1);
int y = creat(str2);
cd[x]++;
rd[y]++;
lj(x,y);
}
int bj = nfind(1);
int flag = 1;
for(int i = 2;i < num;i++)
{
if(bj != nfind(i))
{
flag = 0;
printf("Impossible\n");
break;
}
}
if(flag)
{
int js1 = 0,js2 = 0,js3 = 0;
for(int i = 1;i < num;i++)
{
if(rd[i] - cd[i] == 1)
js1++;
else if(cd[i] - rd[i] == 1)
js2++;
else
js3++;
}
if(js1 == 1 && js2 == 1 && js1 + js2 + js3 == num - 1)
printf("Possible\n");
else if(js1 == 0 && js2 == 0 && js3 == num - 1)
printf("Possible\n");
else
printf("Impossible\n");
}
return 0;
}