P1196 [NOI2002] 银河英雄传说
P1196 [NOI2002] 银河英雄传说
A将战舰划分成30000列,每列依次编号为1,2,...,30000。战舰也依次编号为 1,2,...,30000,让第i 号战舰处于第i 列。
合并指令为M i j,第i号战舰整体(头在前尾在后)接至第 j号战舰所在队列的尾部。战舰队列是由处于同一列的战舰组成的。
B在A发布指令调动舰队的同时,也会发出一些询问指令:C i j。A的第i号战舰与第j号战舰当前是否在同一列中,如果在同一列中,那么它们之间布置有多少战舰。
输入格式
第一行有一个整数 T(1≤T≤5×105),表示总共有 T 条指令。
以下有 T 行,每行有一条指令。指令有两种格式:
M i j:i 和 j 是两个整数(1≤i,j≤30000),表示指令涉及的战舰编号。该指令是莱因哈特窃听到的杨威利发布的舰队调动指令,并且保证第 i 号战舰与第 j 号战舰不在同一列。C i j:i 和 j 是两个整数(1≤i,j≤30000),表示指令涉及的战舰编号。该指令是莱因哈特发布的询问指令。
输出格式
- 调动指令不要输出任何信息。
- 询问指令:在同一列上,输出第 i 号战舰与第 j 号战舰之间布置的战舰数目。不在同一列上,则输出 −1。
**输入 **
4
M 2 3
C 1 2
M 2 4
C 4 2
**输出 **
-1
1
样例解释
战舰位置图:表格中阿拉伯数字表示战舰编号

题目中没有强制 \(i \neq j\),但是实测数据中不存在 \(i = j\) 的情况
#include <bits/stdc++.h>
using namespace std;
const int N = 3e4 + 10;
int f[N] , d[N] , fumo[N] , a , b , t , m , n;
char c;
// 查找函数
int find(int x) {
if (f[x] == x) return x;
int m = f[x];//记录x的父节点
int n = find(f[x]);//递归查找父节点的根节点
f[x] = n;//路径压缩
d[x] += d[m];//// 更新x到根节点的距离
return n;
}
// 合并函数
void baka(int m, int n) {
m = find(m);//仙找根节点
n = find(n);
if (m!= n) {
f[m] = n;
d[m] = fumo[n];
fumo[n] += fumo[m];
}
}
int main() {
scanf("%d", &t);
// 初始化
for (int i = 1; i <= 30000; i++) {
f[i] = i;//父节点初始化为自己
fumo[i] = 1;//开始每个元素单独构成一个集合
d[i] = 0;//每个元素是自己的根节点
}
while (t--)
{
scanf(" %c %d %d", &c, &a, &b);
if (c == 'M')baka(a, b);
else {
m = find(a);n = find(b);
if (m!= n)
{
printf("-1\n");
} else {
printf("%d\n", abs(d[a] - d[b]) - 1);//初始d[i]为0,计算中间个数的时候要减1
}
}
}
return 0;
}




浙公网安备 33010602011771号