poj1703

本题主要算法并查集,一般解决集合合并,是否在同一集合,一个集合中的元素个数等问题。复杂一点的就是带偏移量的,本题和1182很像,但是这个是只有两种情况。下面有个优化的算法。但是不是太多。

//594MS
/*#include<iostream>
#define N 100010
using namespace std;
int n,f[N],rank[N];

int cal(int a)
{
 int t=0;
 while(f[a]!=-1)
 {
  t+=rank[a];
  a=f[a];
 }
 return t;
}

int Find(int t)
{
 while(f[t]!=-1)
  t=f[t];
 return t;
}

void Union(int a,int b)
{
 int x,y;
 x=Find(a);
 y=Find(b);
 if(cal(a)<cal(b))
 {
  f[x]=y;
  rank[x]=(cal(a)-cal(b)+1)%2;
 }
 else
 {
  f[y]=x;
  rank[y]=(cal(a)-cal(b)+1)%2;
 }
}

int main()
{
 int i,j,k,m,x,y;
 char ch;
 scanf("%d",&k);
 while(k--)
 {
  scanf("%d%d",&n,&m);
  memset(f,-1,sizeof(f));
  memset(rank,0,sizeof(rank));
  while(m--)
  {
   getchar();
   scanf("%c %d %d",&ch,&x,&y);
   
   if(ch=='A')
   {
    if(Find(x)!=Find(y))
    {
     printf("Not sure yet./n");
     
    }
    else
    {
     if((cal(x)-cal(y))%2==0)
      printf("In the same gang./n");
     else
      printf("In different gangs./n");
    }
   }
   else if(ch=='D')
   {
    if(Find(x)!=Find(y))
     Union(x,y);
   }
  }
 }
 return 0;
}*/

 

我优化了一下。

//391MS
#include<iostream>
#define N 100010
using namespace std;
int n,f[N],rank[N];

void Init()
{
 for(int i=1;i<=n;i++)
 {
  f[i]=i;
  rank[i]=0;
 }
}

int Find(int x)
{
 if(x==f[x])
  return x;
 int tmp=Find(f[x]);
 
 rank[x]=(rank[x]+rank[f[x]])%2;//由于最终的根节点rank为0,所以不会改变偏移量,反而带偏移量下面的子节点就会相应改变
 f[x]=tmp;
 return f[x];
}

void Union(int a,int b)
{
 int x,y;
 x=Find(a);
 y=Find(b);
 f[x]=y;
 rank[x]=(rank[a]+rank[b]+1)%2;//修改根存偏移量,在find的 时候依次更新子节点。
}

int main()
{
 int k,m,x,y;
 char ch;
 scanf("%d",&k);
 while(k--)
 {
  
  scanf("%d%d",&n,&m);
  Init();
  while(m--)
  {
   getchar();
   scanf("%c %d %d",&ch,&x,&y);
  /* //时间没什么改变,如果改成下面的代码。
   if(ch=='A')
   {
    if(Find(x)!=Find(y))
    {
     printf("Not sure yet./n");
     
    }
    else
    {
     if(rank[x]==rank[y])
      printf("In the same gang./n");
     else
      printf("In different gangs./n");
    }
   }
   else if(ch=='D')
   {
    if(Find(x)!=Find(y))
     Union(x,y);
   }*/
   if(Find(x)!=Find(y))
   {
    if(ch=='A')
    {
     printf("Not sure yet./n");
     continue;
    }
    else
    {
     Union(x,y);
    } 
   }
   else
   {
    if(ch=='A')
    {
     if(rank[x]==rank[y])
      printf("In the same gang./n");
     else
      printf("In different gangs./n");
    }
   }


  }
 }
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值