zoukankan      html  css  js  c++  java
  • 洛谷 [p1196] 银河英雄传说

    所谓带权并查集

    本题所求的不止是两个编号之间是否有关系,还要求两个编号之间有什么关系,这就要求我们维护多个数组,fa[]数组维护两个编号之间的连通性,dis[]维护编号为i的战舰到fa[i]之间的距离,num[]维护编号为i的战舰所在的那一列有多少战舰。

    find函数

    int find(int x){
        if(x!=fa[x]){
            int k=fa[x];
            fa[x]=find(fa[x]);
            dis[x]+=dis[k];
            num[x]=num[fa[x]];
        }
        return fa[x];
    }
    

    每次find的时候都更新num数组与dis数组

    合并函数

    void merge(int x,int y){
        int r1=find(x),r2=find(y);
        if(r1!=r2){
            fa[r1]=r2;
                    dis[r1]=dis[r2]+num[r2];
            num[r2]+=num[r1];
            num[r1]=num[r2];
        }
    }
    

    合并时由于是将i号战舰所在的那一列并到j号所在列的尾端,所以dis[r1]=dis[r2]+num[r2]。

    询问函数

    int query(int a,int b){
        int r1=find(a),r2=find(b);
        if(r1!=r2){
            return -1;
        }else {
            return abs(dis[a]-dis[b])-1;
        }
    }
    

    注意返回时要加一

    AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN=30005;
    int read(){
        int rv=0,fh=1;
        char c=getchar();
        while(c<'0'||c>'9'){
            if(c=='-') fh=-1;
            c=getchar();
        }
        while(c>='0'&&c<='9'){
            rv=(rv<<1)+(rv<<3)+c-'0';
            c=getchar();
        }
        return rv*fh;
    }
    int fa[MAXN],dis[MAXN],t,num[MAXN];
    int find(int x){
        if(x!=fa[x]){
            int k=fa[x];
            fa[x]=find(fa[x]);
            dis[x]+=dis[k];
            num[x]=num[fa[x]];
        }
        return fa[x];
    }
    void merge(int x,int y){
        int r1=find(x),r2=find(y);
        if(r1!=r2){
            fa[r1]=r2;dis[r1]=dis[r2]+num[r2];
            num[r2]+=num[r1];
            num[r1]=num[r2];
        }
    }
    int query(int a,int b){
        int r1=find(a),r2=find(b);
        if(r1!=r2){
            return -1;
        }else {
            return abs(dis[a]-dis[b])-1;
        }
    }
    int main(){
        freopen("in.txt","r",stdin);
        t=read();
        for(int i=1;i<=MAXN;i++) {fa[i]=i;num[i]=1;}
        for(int i=1;i<=t;i++){
            char c;
            scanf(" %c ",&c);
            int a=read(),b=read();
            if(c=='M'){
                merge(a,b);
            }else {
                printf("%d
    ",query(a,b));
            }
        }
    
        fclose(stdin);
        return 0;
    }
    
  • 相关阅读:
    【总结整理】令人惊喜的app
    【总结整理】还没被网购取代的场景
    【总结整理】需求原因
    【总结整理】好的业务架构有哪些特征?
    【总结整理】交互要点
    【总结整理】交互心理学---摘自《人人都是产品经理》
    【总结整理】用户需求--摘自《人人都是产品经理》
    【总结整理】UGC内容
    ArcGIS Runtime SDK for Android 授权(arcgis android 去除水印)
    【原创翻译】ArcGis Android 10.2.4更新内容简介
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/7868344.html
Copyright © 2011-2022 走看看