POJ 1308(并查集) (Data_Structure)

        满足一下条件是树:

 (1)只有一个根;

 (2)一个入度为0的节点,其他节点入度都为1

   

第一个用并查集,第二个搞个数组统计下就OK。

我用set来存点,因为这些点在输入中可能出现多次,用set只会存一次,set方便些啦!

 

代码:

#include <cstdio>
#include <cstdlib>
#include <set>
#include <iterator>
#define N 10001
using namespace std;
                  
set<int> s;
set<int>::iterator iter;

int father[N];
int degree[N];

void make_set();
int find_set(int x);
void unin(int x,int y);

int main()
{
   int i,j,f,a,b,k,zero;
   bool fail;
   
     k = 1 ;
     while(scanf("%d%d",&a,&b) && (a!= -1 && b != -1))
     {
          /*
            空树也是树 
          */
          if( a == 0 && b == 0)
          {
            printf("Case %d is a tree.\n",k++); 
            continue;   
          }
          /*
            每组数据都得清空 set容器 
          */
          s.clear();
          
          s.insert(a);
          s.insert(b);       
          /*
            初始化 
          */   
          make_set();           
          unin(a,b);
          
          ++degree[b];
          
          while(scanf("%d%d",&a,&b) && (a&&b))
          {
             s.insert(a);
             s.insert(b);
             unin(a,b);
             ++degree[b];                                                
          }
        
          f = find_set(father[*s.begin()]);
          zero = 0 ;//统计有几个入度为 0 的点 
          fail = false;
          
          for( iter = s.begin(); iter != s.end(); ++iter)
          {
             /*
               树的每个点的祖先都一样,否则不是树 
             */
              if(f != find_set(father[*iter]))
              {
                   fail = true;
                   break; 
              }      
             /*
               树不能有入度大于 1的节点,否则不是树 
             */
              if(degree[*iter]>1) 
              {
                   fail = true;
                   break;                    
              }
              else
              {
                  /*
                   统计根 
                  */
                  if(degree[*iter] == 0)
                  ++zero;    
              }
              
          }
          
          printf("Case %d ",k++);
          if(fail || zero != 1)
          {
                printf("is not a tree.\n");  
          }
          else
          printf("is a tree.\n");
     }
   return 0;
}
 
void make_set()
{
   int i;
   for(i= 1; i < N; ++i)
   {
      father[i] = i;
      degree[i] = 0;       
   }     
}

int find_set(int x)
{
    int t;
    if(x != father[x])
    father[x] = find_set(father[x]);//路径压缩 
    return father[x];
}
/*
  因为是树,合并是有方向的 
*/
void unin(int x,int y)
{
   x = find_set(x);
   y = find_set(y);
   father[y] = x;
}
        

  

       

posted @ 2012-04-11 21:14  开开甲  阅读(317)  评论(0编辑  收藏  举报