POJ 1988相对偏移

//不容易啊,终于自己a了一道这种类型的题


//
#include<stdio.h>
#include<iostream>
using namespace std;
const int N=30010;
struct node {
int front,last,count;
}pre[N];
int find(int x) {//指向队尾
if(x!=pre[x].last) {
         int h=pre[x].last;
pre[x].last=find(pre[x].last);
pre[x].count=pre[h].count+pre[x].count;//路径压缩
}
return pre[x].last;
}
int find1(int x) {//求队首相当于一个元素指向两个方向,这个指向队首
if(x!=pre[x].front)
pre[x].front=find1(pre[x].front);
return pre[x].front;
}
int main() {
int n,i,a,b,f1,f2;
char  s[2];
while(scanf("%d",&n)!=EOF) {
for(i=1;i<=N;i++) {
pre[i].last=i;
pre[i].front=i;
pre[i].count=0;
}
while(n--) {
scanf("%s",s);
if(s[0]=='M') {
scanf("%d%d",&a,&b);
 f1=find(a);//a集合的队尾
 f2=find(b);
 if(f1==f2)//如果有相同的根节点不用再加了
 continue;
 f2=find1(b);//求b集合的队首
 pre[f1].last=f2;//a集合队尾指向b集合队首
 pre[f1].count=1;//权值为1
         pre[f2].front=f1;//b集合的队首指向a集合的队尾
}
else  {
scanf("%d",&a);
        find(a);
printf("%d\n",pre[a].count);
}
}
}
return 0;
}
//我在网上看了个代码我承认我的方法没有人家的好我又写了一下

#include<stdio.h>
#include<iostream>
using namespace std;
const int N=30010;
int  pre[N],dis[N],sondis[N];
int find(int x) {
 if(x!=pre[x]) {
  int h=pre[x];
  pre[x]=find(pre[x]);
  dis[x]+=dis[h];
 }return pre[x];
}
void unions(int x,int y) {
 int f1=find(x);
 int f2=find(y);
 if(f1==f2)
  return ;
 pre[f1]=f2;
 dis[f1]=sondis[f2]+1;
 sondis[f2]=sondis[f2]+sondis[f1]+1;
}
int main() {
 int n,m,i,j,k,a,b;
 char s[2];
 while(scanf("%d",&n)!=EOF) {
  for(i=1;i<=N;i++) {
   pre[i]=i;
   dis[i]=0;
   sondis[i]=0;
  }
  while(n--) {
   scanf("%s",s);
   if(s[0]=='M') {
    scanf("%d%d",&a,&b);
    unions(a,b);
   }
   else {
    scanf("%d",&a);
    find(a);
    printf("%d\n",dis[a]);
   }
  }
 }
 return 0;
}

posted @ 2013-11-27 19:16  HYDhyd  阅读(96)  评论(0编辑  收藏  举报