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;
}



转载于:https://www.cnblogs.com/Mathics/p/3681190.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值