HDOJ 1829 A Bug's Life

来源:互联网 发布:南师大艺考成绩算法 编辑:程序博客网 时间:2024/05/01 09:36

               刚开始的思路好像不是并查集来着,后来想了很久还是没好的做法。最后搜了一下大致的思想便开始做了。一切搞定之后,提交WA,后来用以下两组数据测试了一下

 4 3                  4 3
1 2     或者     1 2
3 4                  3 4
1 3                  1 4
果然不行。
WA的想法:用单个数组存储每个位置的bug的性别。在合并的部分,进行性别的检测。若无冲突则将第一棵树的root性别取反,并赋值给第二棵树的root,在下次查找的时候自上而下的依据深度的奇偶性和root性别依次更新节点性别。这样想法的错误之处在于:第一,两棵树的root并无直接的性别关系,强制认为性别相反必然出错。第二,合并的过程中完全没有体现合并的依据是两个“节点”的奇偶相反,既然发现了错误,接下来就是问题的关键了。只需要根据“两节点”设置两棵树的root(未合并前),即可在下次的搜索中依据根节点的子节点(即为合并前的root)自上而下的更新所有后代节点的性别了。
            设置的方法是:如果两节点值相同则需要更改root节点的性别,否则不需要,若所有的root节点的性别初始化为0,则设置方法可为:gender[ry]=gender[x]^gender[y]^true;

代码如下:

#include <stdio.h>#include <memory.h>#define N 2005int set[N];bool gender[N];bool flag;int find(int x){if(set[x]==-1)return x;int temp=set[x];set[x]=find(set[x]);gender[x]^=gender[temp];return set[x];}void merge(int x,int y){int rx,ry;rx=find(x),ry=find(y);if(rx!=ry){set[ry]=rx;gender[ry]=gender[x]^gender[y]^true;//here is the reason}else if(gender[x]==gender[y])flag=true;}int main(){//freopen("A Bug's Life.txt","r",stdin);int num,caseNumber,x,y;scanf("%d",&num);for(int i=1;i<=num;i++){flag=false;scanf("%d%d",&caseNumber,&caseNumber);memset(gender,0,sizeof(gender));memset(set,-1,sizeof(set));for(int j=0;j<caseNumber;j++){scanf("%d%d",&x,&y);if(flag) continue;merge(x,y);}if (flag)printf("Scenario #%u:\nSuspicious bugs found!\n\n",i);elseprintf("Scenario #%u:\nNo suspicious bugs found!\n\n",i);}}