首页 > 其他 > 详细

poj 1182 并查集

时间:2014-03-04 15:34:16      阅读:431      评论:0      收藏:0      [点我收藏+]
bubuko.com,布布扣


 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<string>
 4 #include<string.h>
 5 #include<map>
 6 #include<math.h>
 7 #define N 50005
 8 using namespace std;
 9 // rank[x] 表示 parent[x]与x 的关系, rank[x]=0 同类, rank[x]=1 根吃x, rank[x]=2 , x吃根
10 int rank[N]; 
11 int parent[N];
12 int n;
13 void init()
14 {
15     for(int i=1;i<=n;i++)
16     {
17         parent[i]=i;
18         rank[i] = 0;
19     }
20 }
21 int Find(int x)
22 {
23     if(x== parent[x]) return x;
24     int temp_parent=parent[x];
25     parent[x]=Find(parent[x]);
26     rank[x]=(rank[temp_parent]+rank[x])%3;  //因为,根节点连到另一个新的根节点后,根节点有变化,故需要更新x到新节点的关系
27     return parent[x];
28 }
29 void Union(int x, int y,int D)
30 {
31      int xf=Find(x);
32      int yf=Find(y);
33      parent[xf]=yf;
34      rank[xf]=(rank[y]+D-rank[x]+3 )%3;  // 更新根节点到另一个根节点的关系
35 }
36 int main()
37 {
38     int m;
39     scanf("%d%d",&n,&m);
40 
41     int i,j,D,u,v,sum=0;
42     init();
43     for(int i=0;i<m;i++)
44     {
45         scanf("%d%d%d",&D,&u,&v);
46         if(u>n || v>n ||(D==2 && u==v)) {
47             sum++;
48             continue;
49         }
50         int uu= Find(u);
51         int vv= Find(v);
52         if(uu == vv)   //属同一子集,可以判断关系
53         {
54             if((rank[u] - rank[v] +3)%3 !=D-1)
55                 sum++;
56         }
57         else  
58         {
59 
60             Union(u,v,D-1);
61         }
62     }
63     printf("%d\n",sum);
64 
65     return 0 ;
66 }
bubuko.com,布布扣

 1.p[x]表示x的根结点。r[x]表示p[x]与x的关系。r[x] == 0 表示p[x]与x同类;1表示p[x]吃x;2表示x吃p[x]。

2 怎样划分 集合。

注意,这里不是根据x与p[x]是否是同类来划分。而是根据“x与p[x]能否确定两者之间的关系”来划分,若能确定x与p[x]的关系,则它们同属一个集合。

 3.怎样判断一句话是不是假话?
        假设已读入 D , X , Y , 先利用find_set()函数得到X , Y 所在集合的代表元素 rx , ry ,若它们在同一集合(即 rx == ry )则可以判断这句话的真伪( 据 2. ).
        若 D == 1 而 r[X] != r[Y] 则此话为假。(D == 1 表示X与Y为同类,而从r[X] != r[Y]可以推出 X 与 Y 不同类。矛盾。)
        若 D == 2 而 r[X] == r[Y] (X 与Y为同类)或者 r[X] == ( r[Y] + 1 ) % 3 (Y吃X )则此话为假。

 

若 ( r[Y] - r[X] + 3 ) % 3 != D - 1 ,则此话为假。(来自poj 1182中的Discuss )

 5.其他注意事项:
        在union_set( rx , ry )过程中若将S(ry)合并到S(rx)上,则相应的r[ry]必须更新为ry相对于rx的关系。怎样得到更新关系式?用向量运算。
         现在已知关系: rx与x, ry与y, x与y,现在求rx与ry的关系。学过向量应该能做出来吧。。。

     //以下来自poj 1182 中的Discuss

 在find_set( x )过程中要更新所有从x到rx路径上的结点与代表元素的相对关系。

poj 1182 并查集,布布扣,bubuko.com

poj 1182 并查集

原文:http://www.cnblogs.com/zn505119020/p/3579317.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!