**
洛谷oj:P1196银河英雄传说
**
#题目描述
#并查集的题
#注意并查集就是只能一次更新一个的位置信息 如果更新一段就没有意义了
#知识点
并查集
#代码
第1次 更新一段了 就没有意义了 超时了
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<stdio.h>
using namespace std;
#define Maxn 30020
int father[Maxn],next[Maxn],num[Maxn];// next 下一个的编号 num 舰队中飞船的数量
void init()
{
for(int i=1;i<=30000;i++)
{
father[i] = i;
next[i] = -1;
num[i] = 1;
}
}
int Find(int x)
{
if(x != father[x])
{
father[x] = Find(father[x]);
}
return father[x];
}
void add(int rx,int ry)
{
int i;
int cnt = num[ry];
next[cnt] = rx;
///num[ry] = num[rx] + num[ry];
for(i = ry;num[ry]!=1;i = next[i])/// 注意num里面放根节点就是舰队飞船数量 放其他就是所在位置
{
num[i] += num[rx];
}
num[i] += num[rx];
}
void Union(int rx,int ry)
{
if(rx == ry)
{
return ;
}else
{
father[rx] = ry;
add(rx,ry);#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<stdio.h>
using namespace std;
#define Maxn 30020
int father[Maxn],next[Maxn],num[Maxn];// next 下一个的编号 num 舰队中飞船的数量
void init()
{
for(int i=1;i<=30000;i++)
{
father[i] = i;
next[i] = -1;
num[i] = 1;
}
}
int Find(int x)
{
if(x != father[x])
{
father[x] = Find(father[x]);
}
return father[x];
}
void add(int rx,int ry)
{
int i;
int cnt = num[ry];
next[cnt] = rx;
///num[ry] = num[rx] + num[ry];
for(i = ry;num[ry]!=1;i = next[i])/// 注意num里面放根节点就是舰队飞船数量 放其他就是所在位置
{
num[i] += num[rx];
}
num[i] += num[rx];
}
void Union(int rx,int ry)
{
if(rx == ry)
{
return ;
}else
{
father[rx] = ry;
add(rx,ry);
}
}
int main()
{
int t,a,b;
char temp;
init();
cin >>t;
while(t--)
{
cin >> temp >> a >> b;
int ra = Find(a);
int rb = Find(b);
if(temp == 'M')
{
Union(ra,rb);
}else
{
if(ra != rb)
{
cout << "-1" <<endl;
}
else
{
if(num[a] >= num[b])
{
cout << num[a]-num[b]-1 <<endl;
}
else
{
cout << num[b]-num[a]-1 <<endl;
}
}
}
}
return 0;
}
}
}
int main()
{
int t,a,b;
char temp;
init();
cin >>t;
while(t--)
{
cin >> temp >> a >> b;
int ra = Find(a);
int rb = Find(b);
if(temp == 'M')
{
Union(ra,rb);
}else
{
if(ra != rb)
{
cout << "-1" <<endl;
}
else
{
if(num[a] >= num[b])
{
cout << num[a]-num[b]-1 <<endl;
}
else
{
cout << num[b]-num[a]-1 <<endl;
}
}
}
}
return 0;
}
第二次 将更新的大头调到Find函数中 故而可行了
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<math.h>
#include<iostream>
#include<stdio.h>
using namespace std;
#define Maxn 30020
int father[Maxn],Front[Maxn],num[Maxn];//! 并查集数组 前缀和数组(求到根节点的距离 不一定是舰队头) 飞船数量数组
void init()
{
for(int i=1;i<=30000;i++)
{
father[i] = i;
Front[i] = 0;
num[i] = 1;
}
return ;
}
int Find(int x)
{
if(x == father[x])
return x;
int cn = Find(father[x]);
Front[x] += Front[father[x]];///要的是没有更新的那个位置 这个点到原根节点的距离 加上 原根节点到现根节点的距离 是现在节点到现根节点(战舰头)的距离
return father[x] = cn;
}
void Union(int x,int y)
{
father[x] = y;
Front[x] += num[y];
num[y] += num[x];
num[x] = 0;
}
int main()
{
int t,a,b,ra,rb;
char temp;
init();
cin >>t;
while(t--)
{
cin >> temp >> a >> b;
ra = Find(a);
rb = Find(b);
if(temp == 'M')
{
Union(ra,rb);
}else
{
if(ra != rb)
{
cout << "-1" <<endl;
}else
{
cout << abs(Front[a] - Front[b])-1 <<endl;
}
}
}
return 0;
}
#总结
题目逻辑不难 但要优化 要思考如何才能更好的优化 优化时间卡的很死