zoukankan      html  css  js  c++  java
  • P1196 [NOI2002]银河英雄传说

    传送门

    并查集

    起初我也不懂,后来是看了题解才懂的

    感谢https://www.luogu.org/space/show?uid=79044

    尽力讲清楚吧..

    带权并查集..

    并查集在路径压缩时顺带把并查集上的边权也压缩

    设 sum[i] 表示船 i 前面有多少船,不包括 i

    求两船之间有多少船,只要把后面的sum减去前面的sum

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=(x<<1)+(x<<3)+(ch^48);
            ch=getchar();
        }
        return x*f;
    }
    int n;
    int fa[30007],sum[30007],sz[30007];
    //sz[i]表示船i所在的行队列的大小 inline
    int find(int x) { if(fa[x]==x) return x; int k=fa[x]; fa[x]=find(fa[x]);//先更新前面的船的sum和sz sum[x]+=sum[k];
       //利用前面的信息更新当前信息,注意是"+=sum[k]",因为之前可能也压缩过(即x和k之间可能隔着船) sz[x]
    =sz[fa[x]];//更新sz return fa[x]; }//并查集带权路径压缩(核心代码) int main() { for(int i=1;i<=30005;i++) fa[i]=i,sz[i]=1;//初始化 int a,b; char ch; cin>>n; while(n--) { cin>>ch; a=read(); b=read(); if(ch=='M') { int xa=find(a),xb=find(b); //cout<<xa<<" "<<xb<<endl; fa[xa]=xb; sum[xa]+=sz[xb];//更新sum[xa],因为是xa的那一列插在xb那一列后面 sz[xa]+=sz[xb];//更新sz[xa] sz[xb]=sz[xa];//这时xa和xb在同列,所以sz一样 } if(ch=='C') { int xa=find(a),xb=find(b); //cout<<xa<<" "<<xb<<endl; if(xa!=xb) cout<<-1<<endl; else cout<<abs(sum[a]-sum[b])-1<<endl;//注意要减1,因为包括最后面的船b }//查询 } return 0; }
  • 相关阅读:
    调试
    node笔记汇总
    移动端布局
    css 易错点总结
    Angular笔记
    CANVAS笔记
    http笔记汇总
    各种环境搭建 软件安装等等 参考网址收录
    js中同步异步,任务队列
    node.js之fs模块
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9522890.html
Copyright © 2011-2022 走看看