题目大意:每根木棒两端有颜色,能否拼成一条线,当然连接木棒的两端颜色要相同。
思路:欧拉路:(1)、该图是连通的(2)、节点度数为偶数,或者奇数度节点数不超过2。并查集可以很好求得连通性,至于节点就是每一种颜色,要用到并查集就要用到数字编号,所以就要把每一种颜色的的编号表示出来,所以用到trie。
program:
#include<iostream>
#define maxn 500005
int num,r[maxn],total[maxn];
struct point
{
int n;
point *next[26];
}*head;
void inti(point * &p) //这个指针引用实在不是很懂,(要么传递指向指针的指针进来, 要么使用指针的引用)不过当模板使用先,创建链表的时候
{
p=new point;
p->n=-1;
memset(p->next,0,sizeof(p->next));
}
int change(char * in)
{
//int a;
point *p;
p=head;
int len=strlen(in);
for(int i=0;i<len;i++)//修改成功!yes!
{
int tmp=in[i]-'a';
if(p->next[tmp]==NULL)
inti(p->next[tmp]);//用这个指针创建a的节点 和 创建a 的节点再用指针指着a是一样道理的
p=p->next[tmp];
}
/*while(*in++)
{
a=*in-'a';
if(p->next[a]==NULL) //这个用法有点问题,提交时候RE了,改成上面那个就AC了。
inti(p->next[a]);
p=p->next[a];
}*/
if(p->n==-1) //如果该颜色还未使用过,则新编号,之所以用指针P来表示,是因为尽管是最后一个字母的地址,但是在串中还是唯一的地址
p->n=num++;
return p->n;
}
/*int findroot(int a)
{
while(r[a]!=a)
a=r[a];
return a;
}*/
int findroot(int x)
{
if(r[x]!=x)
r[x]=findroot(r[x]);
return r[x];
}
bool judge1()
{
int e=findroot(0);
for(int i=1;i<num;i++)
if(findroot(i)!=e)
return false;
return true;
}
bool judge2()
{
int num1=0;
for(int i=0;i<num;i++)
{
if(total[i]%2)
num1++;
if(num1>2)
return false;
}
return true;
}
int main()
{
// freopen("cc.txt","r",stdin);
char in1[11],in2[11];
for(int i=0;i<maxn;i++)//初始化父亲
r[i]=i;
inti(head);
while(scanf("%s%s",in1,in2)!=EOF)
{
int u,v;
u=change(in1);//返回的是颜色编号
v=change(in2);
total[u]++;
total[v]++;
r[findroot(v)]=findroot(u);//把u的祖先当成v的祖先的祖先,包含并查集合并的一部分,只是少了高度和数目而已
}
if((!judge1())||(!judge2()))
printf("Impossible\n");
else
printf("Possible\n");
system("pause");
return 0;
}
总结:先看一遍一位大牛这个博客对做这道题应该会有很不错的 帮助,尽管她写的有点繁琐:
http://blog.youkuaiyun.com/lyy289065406/article/details/6647445

889

被折叠的 条评论
为什么被折叠?



