风与平原题解

文章描述了一个平原生态环境中,风对生态平衡的重要性,并引入了一个基于玻璃皿和玻璃管的多细胞生物移动问题。目标是在特定条件下,如何最少使用玻璃皿培养多细胞生物使其在1号玻璃皿中合体。解决方案涉及图论和深度优先搜索算法,以确定最少的培养数量。
摘要由CSDN通过智能技术生成

Background

在广袤的平原上,一股股清风悠然而过,轻轻抚摸着平原上的万物。远处的山峦,像是一条条静静躺卧在平原上的巨龙,慢慢地隐去了身影。而在平原的中央,一片片绿色的农田,在风中起伏着,好像是一片片绿色的海洋,翻滚着无尽的生命力。

这些清风,它们并非只是一阵阵轻柔的触感,而且它们还有着其他的作用。它们是平原的守护神,它们可以带来清新的空气,净化平原的环境,保持平原的生态平衡;它们还是平原中的好友,能够带来适宜的气候条件,帮助农作物生长,提高平原的产量。

在这片平原上,风是生命之源,平原是风的承载之地。它们在这里相互依存、相互扶持,共同构成了这片美丽的自然景观。

风与平原,是一种和谐、美丽而又充满生机的存在。它们的相互依存、相互促进,是自然界中最美好的体现之一,也给人们带来了无限的感动和启示。在这里,我们可以看到自然界的伟大,也可以看到人类与自然的和谐共处。

Description

现在有一个树形容器,这个树形容器由 n 个玻璃皿和 n-1 条玻璃管组成。你可以让玻璃皿中的多细胞生物通过玻璃管进行移动。 你可以进行以下的三种操作:

1. 在任意的只跟一条玻璃管相连接的玻璃皿中培养多细胞生物。

2.移动任意一只多细胞生物(能且仅能通过一根玻璃管,每根玻璃管只能被用一次),这种操作会让被移动的多细胞生物变成单细胞生物(别问我为什么,因为我想不到用什么代替了)。

3.将两只在同一个玻璃皿中的单细胞生物合体为一只多细胞生物。

4.单细胞生物不能通过玻璃管。

由于玻璃皿大小限制,一个玻璃皿中最多存在一只多细胞生物或者两只单细胞生物。

现求,要在 1 号玻璃皿中得到一个多细胞生物,你最少需要在几个皿中培养多细胞生物。

Format

Input

第一行,一个整数 n,表示玻璃皿的数量。

接下来 n-1 行,每行两个整数 u,v 表示编号为 u 和 v 的两个玻璃皿之间有一条玻璃管连接。

Output

一个整数,表示最少培养几个多细胞生物,可以让它们在 1 号玻璃皿中合体为一个多细胞生物。

如果无法合体出一个合格的多细胞生物,输出 −1。

Samples

输入数据 1

5
1 2
1 3
2 4
2 5

输出数据 1

3

Limitation

样例解释:在节点3,4,5 培养多细胞生物。

对于 30%  的数据,n \leqslant 10^3

对于 100%  的数据,n \leqslant 10^6

 思路:

建立一棵双向边的树,从1号节点进行dfs,如果只有一条边与之相连则返回true并把ans_u的值设为1。

否则遍历它的子节点,如果dfs(u,v)等于true,cnt加1。判断时如果cnt\geqslant 2 返回true并把ans_u的值设为最小值加上次小值。

 AC code:

#include <iostream>
#include <vector>
using namespace std;
vector<int>road[1000005];
int ans[1000005];//答案
bool dfs(int u,int fa)//u当前节点,fa父亲节点
{
	if(road[u].size() == 1)//只有1条边
	{
	//	cout << u << endl;
		ans[u] = 1;
		return true;
	}
	int cnt = 0;
	int minn = 1e7,minnn = 1e7;//最小值和次小值
	for(int i = 0;i < road[u].size();i++)
	{
		int v = road[u][i];
		if(v == fa)
		{
			continue;
		}
		if(dfs(v,u))
		{
			cnt++;
			if(ans[v] < minn)
			{
				minnn = minn;
				minn = ans[v];
                //最小值
			}
			else if(ans[v] < minnn)
			{
				minnn = ans[v];
                //次小值
			}
		}
	}
	if(cnt >= 2)//只有两个才行
	{
		ans[u] = minn + minnn;
		return true;
	}
	return false;
 } 
int main()
{
	int n;
	cin >> n;
	for(int i = 1;i < n;i++)
	{
		int u,v;
		cin >> u >> v;
		road[u].push_back(v);
		road[v].push_back(u);
        //建树
	}
	if(dfs(1,0))
	{
		cout << ans[1] << endl;
	}
	else
	{
		cout << -1 << endl;
	}
	return 0;
 } 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值