posts - 403, comments - 310, trackbacks - 0, articles - 7
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

并查集 (2) - PKU1611 The Suspects

Posted on 2007-07-15 11:12 ZelluX 阅读(465) 评论(0)  编辑  收藏 所属分类: Algorithm
突然想通了一开始一直超时的原因。
每次我都是把新的suspect并入第一个元素所在的集合中,但是由于使用了优化后的并集操作,有可能是第一个元素所在的集合并入了新的suspect所在的集合,也就是说此后last变量并没有指向第一个元素所在集合的跟结点。于是在Union方法中,parent[root1]可能得到一个正整数,并导致Find方法死循环(根结点的parent为正)

后来把Find方法放到Union方法中,问题解决了。

#include <iostream>

using namespace std;

const int DEFAULT_SIZE = 100;

class UFSets
{
private:
    
int *parent;
    
int size;
public:
    UFSets(
int s = DEFAULT_SIZE);
    
~UFSets() { delete [] parent; }
    
void Union(int root1, int root2);
    
int Find(int x);
    
void Clear(int n);
};

UFSets::UFSets(
int s)
{
    size 
= s;
    parent 
= new int[size + 1];
    
for (int i = 0; i <= size; i++)
        parent[i] 
= -1;
}

int UFSets::Find(int x)
{
    
int result = x;
    
while (parent[result] >= 0)
        result 
= parent[result];
    
return result;
}

void UFSets::Union(int root1, int root2)
{
    
// The old version didn't contain the following 3 setences.
    root1 = Find(root1);
    root2 
= Find(root2);
    
if (root1 == root2) return;

    
int temp = parent[root1] + parent[root2];
    
if (parent[root2] < parent[root1])
    {
        parent[root1] 
= root2;
        parent[root2] 
= temp;
    }
    
else
    {
        parent[root2] 
= root1;
        parent[root1] 
= temp;
    }
}

void UFSets::Clear(int n)
{
    
for (int i = 0; i < n; i++)
        parent[i] 
= -1;
}

int main()
{
    UFSets sets(
30000);
    
int n, m;
    
while (true)
    {
        cin 
>> n >> m;
        
if (n == 0break;
        sets.Clear(n);
        
for (int i = 0; i < m; i++)
        {
            
int t;
            cin 
>> t;
            
int last, x;
            cin 
>> last;
            last 
= sets.Find(last);
            
for (int j = 1; j < t; j++)
            {
                cin 
>> x;
                sets.Union(last, x);
                
// int temp = sets.Find(x);
                
// if (temp != last)
                
//     sets.Union(last, temp);
            }
        }
        
int result = 1;
        
int target = sets.Find(0);
        
for (int i = 1; i < n; i++)
            
if (sets.Find(i) == target)
                result 
++;
        cout 
<< result << endl;
    }
    
return 0;
}



只有注册用户登录后才能发表评论。


网站导航: