首页 > 其他分享 >P10124 [USACO18OPEN] Family Tree B 题解

P10124 [USACO18OPEN] Family Tree B 题解

时间:2024-11-17 21:45:24浏览次数:1  
标签:sy sx string mother 题解 USACO18OPEN Tree mom lca

思路

这道题目很像找 \(2\) 头牛的最近公共祖先,即 lca, 但是并不用那么麻烦.

因为数据很小,我们可以写一个 山寨版 的 lca.具体如下.

int mother(string x, string y) {
	int res = 0;
	while (y != "") { // 有名字的牛
		if (x == y) return res; // 两头牛的名字相等,说明是同一头牛,返回步数
		y = find_mom(y); // y 去找它的母亲
		res++; // 步数++
	}
	return -1; // 没找到
}

先说下 find_mom 这个函数的功能.

string find_mom(string cow) {
	for (int i = 1; i <= n; i++) 
		if (cow == son[i]) return mom[i];
	return "";
} 

就是找一头牛的母亲,如果没有找到,返回空白字符串.

再讲一下 son[i] 和 mom[i].

son[i] 存储孩子,mom[i] 存储母亲.

言归正传,首先 y != "" 是要表明这头牛是在数组中的.

res 是用来存 y 到 x 的步数.所以,在这个函数中,\(x\) 是 不动的,\(y\) 是在 的.

因为题目中的输出是遵循 年纪老的在前,年轻牛在后,所以我们需要存储 \(2\) 个变量.

\(sx\), \(sy\),分别表示 \(x\), \(y\) 到它们的 最近公共祖先的步数.

基本操作顺序

第一次,我们先假设 lca 为奶牛 x. 如果 lca 不为空且它和奶牛 y是有直系关系的,那么不用在找了.

否则,我们动 lca,步数存在 \(sx\) 中.

如果退出循环后 lca 为空,说明 x 和 y 没有关系.

然后我们就可以去查询 y 到 lca 的步数,即 \(sy\).

判断

如果 sx 和 sy 的值均为 1,说明它们只需要各动 1 步就到 lca 了,也就是说,它们是姐妹关系.

如果两个值均大于 1,那就是 cousin 的关系了.

这两个关系在题目中的图片就可以明白.

接下来就是 great great .... grand mother / aunt 关系了.

先根据 \(sy\) 和 \(sx\) 区分前辈和后辈.因为题目中是以 y 为后辈,所以,当 \(sy > sx\) 时,就要互换身份了.

接下来输出 \(t\) 个 great-.

\(t\) 是 \(sx - 2\) 个. 为什么? 首先 x 时后辈,并且 mothergrand-mother 不需要 grant,所以要减 \(2\).

然后判断要不要输出 grand.

因为只有直系关系才有 grand, 所以当 \(sx > 1\) 并且 \(sy = 0\) 时,才输出 grand.

\(sx > 1\) 是因为 mother 没有 grand, 只有mother 的 mother 及以上才有 grand.

\(sy = 0\) 是为了区分 mother 和 aunt.

然后如果 \(sy = 0\),再输出 mother,否则就是 aunt.

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

int n;
string x, y;
string lca; // 存公共祖先 
string mom[102], son[102];
int sx, sy;

string find_mom(string cow) {
	for (int i = 1; i <= n; i++) 
		if (cow == son[i]) return mom[i];
	return "";
} 

int mother(string x, string y) {
	int res = 0;
	while (y != "") {
		if (x == y) return res;
		y = find_mom(y);
		res++;
	}
	return -1;
}

int main() {
	cin >> n >> x >> y;
	for (int i = 1; i <= n; i++)
		cin >> mom[i] >> son[i];
	lca = x;
	while (lca != "") { // 没有跑出族谱 
		if (mother(lca, y) != -1) 
			break;
		lca = find_mom(lca);
		sx++;
	}
	if (lca == "") {
		printf("NOT RELATED");
		return 0;
	}
	int sy = mother(lca ,y);
	if (sx == 1 && sy == 1) printf("SIBLINGS");
	else if (sx > 1 && sy > 1) printf("COUSINS");
	else {
		if (sy > sx) 
			swap(x, y), swap(sx, sy);
		printf("%s is the ", y.c_str());
		for (int i = 1; i <= sx - 2; i++) 
			printf("great-");
		if (sx > 1 && sy == 0) printf("grand-");
		if (sy == 0) printf("mother");
		else printf("aunt");
		printf(" of %s", x.c_str());
	}
	return 0;
}

标签:sy,sx,string,mother,题解,USACO18OPEN,Tree,mom,lca
From: https://www.cnblogs.com/panda-lyl/p/18551211

相关文章

  • [AGC032B] Balanced Neighbors 题解
    考虑先写个暴力\(O(n2^m)\)的输出一下结果,看一下n=4,5,6的(尤其是n=6的)结果,尤其是每个点像其余哪几个点连边,然后就想到了构造方案。代码constintN=109;intn;inte[N][N];voidskymaths(){read(n);if(n%2==0){rep(i,1,n){......
  • 一些Leetcode关于双指针的简单题解
    26.删除有序数组中的重复项给你一个非严格递增排列的数组nums,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致。然后返回nums中唯一元素的个数。考虑nums的唯一元素的数量为k,你需要做以下事情确保......
  • [题解]AtCoder Beginner Contest 380(ABC380) A~F
    A-123233照题意统计即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;strings;map<char,int>ma;signedmain(){ cin>>s; for(chari:s)ma[i]++; if(ma['1']==1&&ma['2']==2&&ma['3']==3)co......
  • 【星航计划】2024.11 Div. 3 题解
    2024--星航计划--十一月份--基础算法A.分段每一段连续的\(1\)之间是独立的,我们只需要关心一段连续的1的结果。可以证明对于一段连续的\(1\),最优策略是将其划分成多个单独的\(1\)以及可能余下的连续两个\(1\)。对于\(k\)个连续的\(1\),如果\(k\)是奇数,......
  • 【学校训练记录】11月个人训练赛4个人题解
    A题意可以理解为在a,b的范围内如果一个数是某个整数的立方,求与其距离为k的范围内有几个整数的平方数,我们可以对于每个立方数求出其数量,注意边界问题#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;inta,b,k;voidsolve(){ cin>>a>>b>>k; in......
  • 【未完结】 AtCoder Beginner Contest 380 题解
    AtCoderBeginnerContest380Rated:\(770\)A-123233简单模拟B-HurdleParsing字符串模拟C-MoveSegment找到第\(k\)个块的下标,模拟。D-StrangeMirroringE-1DBucketToolF-ExchangeGameG-AnotherShuffleWindow......
  • CF603E Pastoral Oddities 题解
    Description给定一张\(n\)个点的无向图,初始没有边。依次加入\(m\)条带权的边,每次加入后询问是否存在一个边集,满足每个点的度数均为奇数。若存在,则还需要最小化边集中的最大边权。\(n\le10^5\),\(m\le3\times10^5\)。Solution考虑给定一个图,怎么判断这个图存在一个......
  • K-D Tree
    0.前言K-DTree是一种能够处理高维空间信息的数据结构,其在一些情况下能够代替CDQ分治以及树套树,较优秀地处理\(k\)维空间上的信息。参考资料:OI-wiki题单:\(\tt{Link}\)1.KDT的原理KDT的结构与BST类似,其每一个非叶子节点都具有超平面的作用,建树时会选择\(k\)维中某......
  • 2021 Hubei Provincial Collegiate Programming Contest/2021湖北省赛 题解
    按解决顺序排列目录FAIDHECKJGBF二分答案ans,放最小的前ans个bi(变成必须放完)因为bi=2^k,所以小的放了可能会拆散大的空间,大的把小的地方占了的话小的可以塞其他地方,所以先放大的然后暴力能放则放,最多log次指针回到开头所以一次求解O(nlogn),总复杂度log^2A模拟,暴力枚举暴力异......
  • ABC380题解(F&G)
    ABC380F.ExchangeGame因为\(n+m+k\leq12\),考虑状压dp,设\(f(x,s1,s2,s3)\)表示先手,后手,桌子上的牌分别是哪一些,这有\(O(3^n)\)种状态。然后只要枚举出哪一张即可,有\(f(s1,s2,s3)\tof(s2,s1-i+j,s3+i-j)(i\ins1,j\ins3,a_j<a_i)\)\(f(s1,s2,s3)\tof(s2,s1-i,s3+i......