• NOI2002 银河英雄传说(luogu p1196)


    原题链接:https://www.luogu.org/problem/show?pid=1196

    luogu 400AC纪念题

    这道题也算是对于并查集的巧妙运用了。

    首先解释一下数组的含义,f[i]表示i号战舰现在正在f[i]列中,num[i]表示目前第i列上有num[i]艘战舰,front[i]表示i号战舰是当前列的第front[i]艘战舰,

    因为特殊的要求,所以在路径压缩的时候就要注意,不能只简单地寻找祖先,而要在寻找祖先的同时将自己所在列的所有战舰都合并到祖先的列,也就是将祖先的front值加到当前点的front值上。

    在合并的指令时,因为当前战舰不一定是最后一艘,仅凭一个front已经不够用了,因此num派上了用场。

    假设fx,fy分别表示x,y的祖先,将x所在列合并到y所在列的时候,就可以直接将num[fy]加到front[fx]上,同时更新num[fy],然后fx位置已经没有战舰了,于是可以清空为0。

    每次询问的时候,首先判断x,y是否在同一列中,这个用并查集就能很快完成,在同一列的话,由于front就代表了他们的位置,所以abs(front[x]-front[y])-1。

    #include<cstdio>
    int f[50005],front[50005],num[50005];
    char s[5];
    int abs(int x)
    {
        return x<0 ? -x : x;
    }
    int find(int x)
    {
        if(x==f[x]) return x;
        int fn=find(f[x]);
        front[x]+=front[f[x]];
        return f[x]=fn;
    }
    int main()
    {
        int t,x,y;
        scanf("%d",&t);
        for(int i=0;i<=50000;i++)
        {
            f[i]=i;
            num[i]=1;
        }
        while(t--)
        {
            scanf("%s %d %d",s,&x,&y);
            int fx=find(x),fy=find(y);
            if(s[0]=='M')
            {
                front[fx]+=num[fy];
                f[fx]=fy;
                num[fy]+=num[fx];
                num[fx]=0;
            }
            else
            {
                if(fx!=fy) printf("-1
    ");
                else printf("%d
    ",abs(front[x]-front[y])-1);
            }
        }
        return 0;
    }
  • 相关阅读:
    SQL Server 复制订阅
    杂谈经验与未来
    泛泰A820L (高通MSM8660 cpu) 3.4内核的CM10.1(Android 4.2.2) 測试版第二版
    hdu1280 前m大的数(数组下标排序)
    Design Pattern Adaptor 适配器设计模式
    ssh命令、ping命令、traceroute 命令所使用的协议
    Android禁止ViewPager的左右滑动
    推荐一款优雅的jquery手风琴特效
    vijos
    iOS 7 UI 过渡指南
  • 原文地址:https://www.cnblogs.com/zeroform/p/7593483.html
Copyright © 2020-2023  润新知