[luoguP1196] 银河英雄传说(并查集)

传送门

记录 up[x] 表示 x 上方有多少个

   all[x] 表示当前连通的有多少个

find 的时候 和 合并的时候 更新一下即可

——代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 30001
 4 #define abs(x) ((x) < 0 ? -(x) : (x))
 5
 6 int T;
 7 int f[N], up[N], all[N];
 8
 9 inline int read()
10 {
11     int x = 0, f = 1;
12     char ch = getchar();
13     for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1;
14     for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘;
15     return x * f;
16 }
17
18 inline int find(int x)
19 {
20     if(x ^ f[x])
21     {
22         int fx = f[x];
23         f[x] = find(f[x]);
24         up[x] += up[fx];
25     }
26     return f[x];
27 }
28
29 int main()
30 {
31     int i, x, y, fx, fy;
32     char s[1];
33     T = read();
34     for(i = 1; i < N; i++) f[i] = i, all[i] = 1;
35     while(T--)
36     {
37         scanf("%s", s);
38         x = read();
39         y = read();
40         fx = find(x);
41         fy = find(y);
42         if(s[0] == ‘M‘)
43         {
44             f[fx] = fy;
45             up[fx] += all[fy];
46             all[fy] += all[fx];
47         }
48         else fx ^ fy ? puts("-1") : printf("%d\n", abs(up[x] - up[y]) - 1);
49     }
50     return 0;
51 }

时间: 2024-08-09 02:17:29

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

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

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

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

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

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;ch

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). 查找 查找元素所在的集合,即根节点. 合并 将两个元素所在的集合合并为一个集合. 通常来说,合并之前,应先判断两个元素是否属于