P1196 银河英雄传说

  这题真的很经典,我WA了三次,最后一次才AC……

  因为这道题是很有技术含量的,能自己写出来真的很厉害(不是在夸自己)。如果只是粗略的去看题解或者抄题解(倒是可以用来蒙骗自己),那这道题就失去意义了。下面的代码,每一句话,都是值得深刻推敲的。

  举几个例子:

int find(int x)
{
    if(x==par[x])
    return x;
    int p=find(par[x]);
    dp[x]+=dp[par[x]];
    return par[x]=p;
}

  这里就不能直接写par [ x ] = find ( par [ x ] ),后面写return par [ x ] 。(为什么想过么?)

  而且粗略地想:深度不应该是父亲 + 1 吗?而且每一次都把深度加一遍,不会有错吗?

  如果你这么想,那么首先你并没有掌握并查集的本质和基础的定义,需要再踏踏实实搞好基础;如果你根本就没想到这一点,而是直接欺骗自己感性地理解,那么你只是背了一个最普通的板子,并且和没学过没有区别,不可能独立敲出这道题。

  而这只是一部分,要不我也不会说这道题经典……

  太晚了,不解释为什么了,如果你感兴趣,可以来窗边第一号机位。

  代码贴上:(可能没有题解写得好)

#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
#define maxn 3000005
int n,dp[maxn],par[maxn],am[maxn];
int find(int x)
{
    if(x==par[x])
    return x;
    int p=find(par[x]);
    dp[x]+=dp[par[x]];
    return par[x]=p;
}
void merge(int x,int y)
{
    int fx=find(x),fy=find(y);
    dp[fx]+=am[fy];
    par[fx]=fy;
    am[fy]+=am[fx];
    am[fx]=0;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    par[i]=i,am[i]=1; 
    for(int i=1;i<=n;i++)
    {
        char s;
        int x,y;
        cin>>s;
        scanf("%d%d",&x,&y);
        if(s=='M')
        merge(x,y);
        else
        {
            int fx=find(x),fy=find(y);
            if(fx!=fy)
            {
                printf("-1\n");
                continue;
            }
            else
                printf("%d\n",abs(dp[y]-dp[x])-1);
        }
    }
}

 

转载于:https://www.cnblogs.com/popo-black-cat/p/10140995.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值