【并查集】猜数

【题目描述】

已知一个数列,我会告诉你某两项的差,然后你要回答我的问题

【输入格式】

第一行是两个数 n,m,表示数列有n项,一共有m条指令。
接下来有m行,每行一个指令,指令分两类:
1. I_i_j_k 表示第i比第j项大k.
2. A_i_j 询问当前第i项与第j项差的绝对值.('_'表示空格)

【输出格式】

对于每个2类指令,输出一行,无法判断时输出-1


我们考虑用并查集来维护,我们维护他与根节点的相对大小

对于加法操作,我们先找到他们各自的根节点,如果不同,就对y点的祖先打上标记,因为我们要使x的查询值比y大z,则应在y的祖先处打上的标记值为fr[x]-fr[y]-z

对于询问操作,若不在并查集则输出-1,否则输出相对大小的绝对值差即可

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<ctime>
using namespace std;
int n,m,f[10005],fr[10005];
char op[1];
int find(int x)
{
	if(x==f[x]) return x;
	int fx=find(f[x]);
	fr[x]+=fr[f[x]];
	f[x]=fx;
	return fx;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) f[i]=i,fr[i]=0;
	for(int i=1;i<=m;i++)
	{
		scanf("%s",op);
		if(op[0]=='I')
		{
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			int fx=find(x),fy=find(y);
			if(fx!=fy)
			{
				f[fy]=fx;
				fr[fy]=fr[x]-fr[y]-z;
			}
		}
		else
		{
			int x,y;
			scanf("%d%d",&x,&y);
			int fx=find(x),fy=find(y);
			if(fx!=fy) printf("-1\n");
			else printf("%d\n",abs(fr[x]-fr[y]));
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Dy_Dream/article/details/85164526