题解 P1196 【[NOI2002]银河英雄传说】
Martin_MHT · · 题解
羞涩,其实这道题我看了题解才过的……
好叭,说说我的思想
这一题明显要用并查集,因为维护队列接龙的时候要用到记录父亲等等操作
而因为每一次输出的时候要输出i-j之间的战舰和
所以我们引入两个数组
- sum数组——记录本列总长
- toh数组——记录每一个点到队首的长度(因为我们压缩了路径,所以要存储)
那么,我们就可以尝试着去打程序了。
find找爸爸函数:
int find(int x)//找x的爸爸
{
if(fat[x]==x)//如果找到根节点,这我就不多说了
return x;
int t1=fat[x],t2=find(fat[x]);//t1是它的父亲,t2是它父亲的父亲
//(爷爷?滑稽)
fat[x]=t2;//更新fat[x]的值
toh[x]+=toh[t1];
/*划重点!因为我们压缩了路径,所以这个点到父亲的距离
要加上新压缩的路径中未计算的点*/
return t2;//返回找到的父亲
}
unionn合并函数
void unionn(int r1,int r2)
{
int f1=find(r1),f2=find(r2);//直接把根节点插上,不多说
fat[f2]=f1;//记录父亲
toh[f2]=sum[f1];//这里到以下全是重点!
//原队列长度即是此节点到父亲的距离
sum[f1]+=sum[f2];//f1队列后放了sum[f2]个战舰
sum[f2]=0;//原队列清空
}
下面是AC code:
#include <cstdio>
#include <iostream>
using namespace std;
int sum[30001],fat[30001],toh[30001],t,ans;
int find(int x)
{
if(fat[x]==x)
return x;
int t1=fat[x],t2=find(fat[x]);
fat[x]=t2;
toh[x]+=toh[t1];
return t2;
}
void unionn(int r1,int r2)
{
int f1=find(r1),f2=find(r2);
fat[f2]=f1;
toh[f2]=sum[f1];
sum[f1]+=sum[f2];
sum[f2]=0;
}
int abs(int op)
{
return op<0?-op:op;
}
int main()
{
char ds;
int u,v;
for(int i=1;i<=30000;i++)
{
fat[i]=i;
sum[i]=1;
}
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
cin>>ds;scanf("%d %d",&u,&v);
if(ds=='M')
{
unionn(v,u);
}
else
{
if(find(u)!=find(v))
printf("-1\n");
else
printf("%d\n",abs(toh[u]-toh[v])-1);
}
}
}
END.蒟蒻%%%dalao!