并查集 (2) - PKU1611 The Suspects

突然想通了一开始一直超时的原因。
每次我都是把新的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  ==   0 break ;
        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 ;
}


你可能感兴趣的:(并查集 (2) - PKU1611 The Suspects)