• 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;
    }
  • 相关阅读:
    JavaScript自动化构建工具grunt、gulp、webpack介绍
    开始使用 Vuejs 2.0 ---简单总结2
    开始使用 Vuejs 2.0 ---简单总结1
    Bootboxjs快速制作Bootstrap的弹出框效果
    FlexSlider是一个非常出色的jQuery滑动切换插件
    CSS实现背景透明,文字不透明(兼容各浏览器)
    jquery中attr和prop的区别
    GitHub 的分支创建与合并
    [译]使用NuGet管理共享代码
    [译]Nuget.Server
  • 原文地址:https://www.cnblogs.com/zeroform/p/7593483.html
Copyright © 2020-2023  润新知