noi2002银河英雄传说(并查集)

首先表示对C++读入读出问题复杂程度的敬畏,看了好多没讲明白的,本题用cin竟然过不了评测,搞scanf的读入搞了好久....

本题确实是一道经典的并查集题型,不多讲,拿来练练手用的(其中经历很惨)

用pre[i]表示i到其父节点f[i]之间排几个(父节点算1个)

f[i]表示i的父节点

num[i]表示i的队伍中一共有多少人

大致即 利用父节点与该点距离进行迭代的过程,即pre[x]=pre[x]+pre[f[x]]; 然后每次调整队伍时只要将父节点的位置搞清楚了,其他点都可以根据与父节点关系计算出来

/*看来对于c++这门语言见解不够,或者说c++确实不好用*/
#include<iostream>
#include<cstdio>
#include<cmath>
int f[30000],pre[30000],num[30000];
using namespace std;
int find(int x){
    if (f[x]==x) return(x);
    find(f[x]);
    pre[x]+=pre[f[x]];
    f[x]=f[f[x]];
    return(f[x]);
}
int main()
{
    int n,i,j,k,a,b,fa,fb;
    char c;
    cin>>n;
    for(k=1;k<=30000;k++){
        f[k]=k;
        num[k]=1;
    }
    for(k=1;k<=n;k++){
        while (getchar()!='\n');//读入问题至今觉得c++的cin和scanf都相当不好用,可能有的作用不知道,但是没找到真正讲得明白其原理的文章;  只能表示pascal的read,readln的强大
        scanf("%c",&c);
        scanf("%d%d",&a,&b);
        fa=find(a);fb=find(b);
        if(c=='M'){
            f[fa]=fb;
            pre[fa]=num[fb];
            num[fb]+=num[fa];
        }
        if(c=='C'){
            if(fa==fb){
                printf("%d\n",((int)abs(pre[a]-pre[b]))-1);//很奇怪的地方,若abs不用int竟然abs返回值变成0,不知为什么?
            }else printf("-1\n");
        }
    }
    return 0;
}



posted @ 2013-10-15 14:02  Estimator  阅读(291)  评论(0编辑  收藏  举报