ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[NOI2002] 银河英雄传说

2022-07-06 11:33:25  阅读:170  来源: 互联网

标签:ch int t2 t1 fa 银河 NOI2002 find 英雄


原题链接

题解

考点:带权并查集。

设 \(d[x]\) 表示 \(x\) 节点前面的战舰数量,\(s[x]\) 表示以 \(x\) 节点为首的那一列战舰的总数,合并操作如下:

void add(int x,int y)
{
	int a=find(x),b=find(y);
	fa[a]=b;
	d[a]=s[b];
	s[b]+=s[a];
	s[a]=0;
}

把 \(a\) 接到 \(b\),\(a\) 前面的就是 \(s[b]\),然后战舰的总数加 \(s[a]\),而 \(a\) 又不作为头,所以清零。

查询操作:

int find(int x)
{
	if(fa[x]==x)return x;
	int t1=fa[x],t2=find(fa[x]);
	fa[x]=t2;
	d[x]+=d[t1];
	return fa[x];
}

因为我们进行了路径压缩,设 \(t1\) 为 \(x\) 原来的父亲,\(t2\) 为 \(x\) 现在的父亲,则 \(d[t1]\) 已经计算正确,然后 \(d[x]\) 就加上 \(d[t1]\)。

Code:

#include<bits/stdc++.h>
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=30000;
int fa[N+100],s[N+100],d[N+100];
int find(int x)
{
	if(fa[x]==x)return x;
	int t1=fa[x],t2=find(fa[x]);
	fa[x]=t2;
	d[x]+=d[t1];
	return fa[x];
}
void add(int x,int y)
{
	int a=find(x),b=find(y);
	fa[a]=b;
	d[a]=s[b];
	s[b]+=s[a];
	s[a]=0;
}
int main()
{
	for(int i=1;i<=N;i++)fa[i]=i,s[i]=1,d[i]=0;
	int n;read(n);
	for(int i=1,x,y;i<=n;i++)
	{
		char c;
		cin>>c;read(x);read(y);
		if(c=='M')add(x,y);
		else
		{
			if(find(x)!=find(y))printf("-1\n");
			else printf("%d\n",abs(d[x]-d[y])-1);
		}
	}
	return 0;
}

标签:ch,int,t2,t1,fa,银河,NOI2002,find,英雄
来源: https://www.cnblogs.com/LAK666/p/16450106.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有