题解 P1196 【[NOI2002]银河英雄传说】
【参考资料】
三体智子的博客 - P1196 [NOI2002]银河英雄传说:https://www.luogu.org/blog/huangweixian123/p1196-noi2002-yin-he-ying-xiong-zhuan-shuo
【题目描述】
公元五八○一年,地球居民迁至金牛座α第二行星,在那里发表银河联邦创立宣言,同年改元为宇宙历元年,并开始向银河系深处拓展。
宇宙历七九九年,银河系的两大军事集团在巴米利恩星域爆发战争。泰山压顶集团派宇宙舰队司令莱因哈特率领十万余艘战舰出征,气吞山河集团点名将杨威利组织麾下三万艘战舰迎敌。
杨威利擅长排兵布阵,巧妙运用各种战术屡次以少胜多,难免恣生骄气。在这次决战中,他将巴米利恩星域战场划分成M i j,含义为第
大。 然而,老谋深算的莱因哈特早已在战略上取得了主动。在交战中,他可以通过庞大的情报网络随时监听杨威利的舰队调动指令。
在杨威利发布指令调动舰队的同时,莱因哈特为了及时了解当前杨威利的战舰分布情况,也会发出一些询问指令:C i j。该指令意思是,询问电脑,杨威利的第
作为一个资深的高级程序设计员,你被要求编写程序分析杨威利的指令,以及回答莱因哈特的询问。
最终的决战已经展开,银河的历史又翻过了一页……
【输入输出格式】
- 输入格式
输入文件的第一行有一个整数
以下有
-
M i j:i 和j 是两个整数(1 \leq i , j \leq 30000 ),表示指令涉及的战舰编号。该指令是莱因哈特窃听到的杨威利发布的舰队调动指令,并且保证第i号战舰与第j号战舰不在同一列。 -
C i j:i 和j 是两个整数(1 \leq i , j \leq 30000 ),表示指令涉及的战舰编号。该指令是莱因哈特发布的询问指令。
- 输出格式
你的程序应当依次对输入的每一条指令进行分析和处理:
如果是杨威利发布的舰队调动指令,则表示舰队排列发生了变化,你的程序要注意到这一点,但是不要输出任何信息;
如果是莱因哈特发布的询问指令,你的程序要输出一行,仅包含一个整数,表示在同一列上,第-1。
【输入输出样例】
- 输入样例
4 M 2 3 C 1 2 M 2 4 C 4 2 - 输出样例
-1 1
【样例说明】
战舰位置图:表格中阿拉伯数字表示战舰编号。
【题目大意】
有-1。
【题解】
我会并查集!
我们考虑用并查集解决这道题目。由于M操作较为简单,因此我们先对M操作入手。我们可以用一个数组size[]来存储每个队列当前所有的飞船的数量,在这里我用size[i]来表示第d[i]来表示
if(t[1]=='M')
{
f[tx]=ty;
d[tx]=size[ty];
size[ty]+=size[tx];
size[tx]=0;
}
接下来我们要处理的就是find()函数,一般我们写并查集的话函数是这样子的:
if(x==f[x])
{
return x;
}
else
{
return f[x]=find(f[x]);
}
但是在本题中,find()函数却是这样子的:
int find(int x)
{
if(f[x]==x)
{
return x;
}
int t1=f[x];
int t2=find(f[x]);
f[x]=t2;
d[x]+=d[t1];
return t2;
}
在上面的一段代码中,f[x]=t2(更新d[x]+=d[t1](增加点
C操作也比较简单,如果两个点的老大不一样就输出-1,否则就输出|d[x]-d[y]|-1即可,不懂的可以自己去算一下。
下面上AC代码~
#include <cstdio>
#include <cstdlib>
int size[1000001],f[1000001],d[1000001];
int inf=30001;
int find(int x)
{
if(f[x]==x)
{
return x;
}
int t1=f[x];
int t2=find(f[x]);
f[x]=t2;
d[x]+=d[t1];
return t2;
}
int main()
{
int n=0;
scanf("%d",&n);
for(int i=1;i<=inf;i++)
{
f[i]=i;
size[i]=1;
}
for(int i=1;i<=n;i++)
{
char t[5];
int x=0,y=0;
scanf("%s %d %d",t+1,&x,&y);
int tx=find(x),ty=find(y);
if(t[1]=='M')
{
f[tx]=ty;
d[tx]=size[ty];
size[ty]+=size[tx];
size[tx]=0;
}
else if(t[1]=='C')
{
if(tx!=ty)
{
printf("-1\n");
}
else
{
printf("%d\n",abs(d[x]-d[y])-1);
}
}
}
return 0;
}