luogu1196 银河英雄传说 (并查集)

并查集,不仅记fa,还记与fa的距离,还记根对应的尾节点

路径压缩的时候更新那个距离就行了

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=3e4+10;
 7
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();}
11     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
12     return x*neg;
13 }
14
15 int fa[maxn],tl[maxn],dis[maxn],T,N=30000;
16
17 inline int getf(int x){
18     if(x==fa[x]) return x;
19     int re=getf(fa[x]);
20     dis[x]+=dis[fa[x]],fa[x]=re;
21     return re;
22 }
23
24 inline void add(int x,int y){
25     int a=getf(x),b=getf(y);
26     fa[a]=tl[b],tl[b]=tl[a],dis[a]=1;
27 }
28
29 int main(){
30     // freopen("testdata.in","r",stdin);
31     int i,j,k;
32     T=rd();
33     for(i=1;i<=N;i++)
34         tl[i]=fa[i]=i;
35     for(i=1;i<=T;i++){
36         char s[5];scanf("%s",s);
37         int a=rd(),b=rd();
38         if(s[0]==‘M‘) add(a,b);
39         else{
40             int x=getf(a),y=getf(b);
41             if(x!=y) printf("-1\n");
42             else printf("%d\n",abs(dis[a]-dis[b])-1);
43         }
44     }
45     return 0;
46 }

原文地址:https://www.cnblogs.com/Ressed/p/9887250.html

时间: 2024-10-09 21:21:46

luogu1196 银河英雄传说 (并查集)的相关文章

洛谷P1196[NOI2002]银河英雄传说-并查集扩展

银河英雄传说 题意:在并查集的基础上,还要求出同一集合的两个点的距离 这道题用并查集自己是知道的,但是竟然可以这么骚的操作. 下面转自大佬的查详细题解 初见这道题,首先想到的方法当然是直接模拟,模拟每一次指令.当然这种方法对于小数据行得通,但对于此题的500,000个指令,肯定超时. 因此我们就要想其它方法. 先来分析一下这些指令的特点,很容易发现对于每个M指令,只可能一次移动整个队列,并且是把两个队列首尾相接合并成一个队列,不会出现把一个队列分开的情况,因此,我们必须要找到一个可以一次操作合并

H20的题——[noip2003]银河英雄传(并查集)

公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压顶集团派宇宙舰队司令莱因哈特率领十万余艘战舰出征,气吞山河集团点名将杨威利组织麾下三万艘战舰迎敌. 杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气.在这次决战中,他将巴米利恩星域战场划分成30000列,每列依次编号为1, 2, …, 30000.之后,他把自己的战舰也依次编号为1, 2, …,

acwing 238. 银河英雄传说 并查集

地址 https://www.acwing.com/problem/content/240/ 有一个划分为N列的星际战场,各列依次编号为1,2,…,N. 有N艘战舰,也依次编号为1,2,…,N,其中第i号战舰处于第i列. 有T条指令,每条指令格式为以下两种之一: 1.M i j,表示让第i号战舰所在列的全部战舰保持原有顺序,接在第j号战舰所在列的尾部. 2.C i j,表示询问第i号战舰与第j号战舰当前是否处于同一列中,如果在同一列中,它们之间间隔了多少艘战舰. 现在需要你编写一个程序,处理一系

P1196 银河英雄传说(加权并查集)

P1196 银河英雄传说 题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压 顶集团派宇宙舰队司令莱因哈特率领十万余艘战舰出征,气吞山河集团点名将杨 威利组织麾下三万艘战舰迎敌. 杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气.在 这次决战中,他将巴米利恩星域战场划分成30000列,每列依次编号为1, 2, …, 30000.之后

浅谈并查集 By cellur925【内含题目食物链、银河英雄传说等】

什么是并查集? 合并!查询!集合! 专业点说? 动态维护若干不重叠的和,支持合并查询的数据结构!(lyd老师说的) 数据结构特点:代表元.即为每个集合选择一个固定的元素,作为整个集合的代表,利用树形结构存储,每个节点都是一个元素,树根是集合的代表元素.(还是lyd老师说的) 两大基本操作 一.合并(merge()) 即把两个集合合并到一个的操作.通俗的说,即令其中一个树根为另一个树根的子节点. void merge(int x,int y) { fa[getf(x)]=getf(y); } 二.

洛谷OJ P1196 银河英雄传说(带权并查集)

题目描述 公元五八○一年,地球居民迁移至金牛座α第二行星,在那里发表银河联邦 创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展. 宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争.泰山压 顶集团派宇宙舰队司令莱因哈特率领十万余艘战舰出征,气吞山河集团点名将杨 威利组织麾下三万艘战舰迎敌. 杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气.在 这次决战中,他将巴米利恩星域战场划分成30000列,每列依次编号为1, 2, …, 30000.之后,他把自己的战舰也依次编号

银河英雄传说(带权并查集)

题意就是要维护并查集,切询问两个点是不是在一棵树上,如果是,输出他们间的数减一 #include<iostream> #include<cstdio> using namespace std; int re(){ char c=getchar();int all=0,pd=1; for(;c>'9'||c<'0';c=getchar()) if(c=='-') pd=-1; while(c>='0'&&c<='9') all=all*10+c

cogs2089 平凡的测试数据 并查集

链接:http://cogs.pro/cogs/problem/problem.php?pid=2089 题意:动态修改n个点之间关系,动态查询点到根路径权值异或和. n<=300000,显然LCT(不会)和树剖会超时.要找到O(n)算法. 想到银河英雄传说一题对路径的处理,维护带权并查集,动态将各个集合合并并更新权值,查询时动态查询根节点 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4

并查集 (Union-Find Sets)及其应用

定义 并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题.常常在使用中以森林来表示. 集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并. 主要操作 初始化 把每个点所在集合初始化为其自身. 通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N). 查找 查找元素所在的集合,即根节点. 合并 将两个元素所在的集合合并为一个集合. 通常来说,合并之前,应先判断两个元素是否属于