HDOJ 1829 A Bug's Life
刚开始的思路好像不是并查集来着,后来想了很久还是没好的做法。最后搜了一下大致的思想便开始做了。一切搞定之后,提交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;
代码如下:
View Code
1 #include <stdio.h>
2 #include <memory.h>
3 #define N 2005
4 int set[N];
5 bool gender[N];
6 bool flag;
7 int find(int x)
8 {
9 if(set[x]==-1)
10 return x;
11 int temp=set[x];
12 set[x]=find(set[x]);
13 gender[x]^=gender[temp];
14 return set[x];
15 }
16 void merge(int x,int y)
17 {
18 int rx,ry;
19 rx=find(x),ry=find(y);
20 if(rx!=ry)
21 {
22 set[ry]=rx;
23 gender[ry]=gender[x]^gender[y]^true;//here is the reason
24 }
25 else if(gender[x]==gender[y])
26 flag=true;
27 }
28
29 int main()
30 {
31 //freopen("A Bug's Life.txt","r",stdin);
32 int num,caseNumber,x,y;
33 scanf("%d",&num);
34 for(int i=1;i<=num;i++)
35 {
36 flag=false;
37 scanf("%d%d",&caseNumber,&caseNumber);
38 memset(gender,0,sizeof(gender));
39 memset(set,-1,sizeof(set));
40 for(int j=0;j<caseNumber;j++)
41 {
42 scanf("%d%d",&x,&y);
43 if(flag) continue;
44 merge(x,y);
45 }
46 if (flag)
47 printf("Scenario #%u:\nSuspicious bugs found!\n\n",i);
48 else
49 printf("Scenario #%u:\nNo suspicious bugs found!\n\n",i);
50 }
51 }

浙公网安备 33010602011771号