L2-020 功夫传人(树的建立和BFS)

简介: L2-020 功夫传人(树的建立和BFS)

描述:


一门武功能否传承久远并被发扬光大,是要看缘分的。一般来说,师傅传授给徒弟的武功总要打个折扣,于是越往后传,弟子们的功夫就越弱…… 直到某一支的某一代突然出现一个天分特别高的弟子(或者是吃到了灵丹、挖到了特别的秘笈),会将功夫的威力一下子放大N倍 —— 我们称这种弟子为“得道者”。


这里我们来考察某一位祖师爷门下的徒子徒孙家谱:假设家谱中的每个人只有1位师傅(除了祖师爷没有师傅);每位师傅可以带很多徒弟;并且假设辈分严格有序,即祖师爷这门武功的每个第i代传人只能在第i-1代传人中拜1个师傅。我们假设已知祖师爷的功力值为Z,每向下传承一代,就会减弱r%,除非某一代弟子得道。现给出师门谱系关系,要求你算出所有得道者的功力总值。


输入:


输入在第一行给出3个正整数,分别是:

N (<=105)——整个师门的总人数(于是每个人从0到N−1编号,祖师爷的编号为0);

Z——祖师爷的功力值(不一定是整数,但起码是正数);

r ——每传一代功夫所打的折扣百分比值(不超过100的正数)。

接下来有N行,第i行(i=0,⋯,N−1)描述编号为i的人所传的徒弟,格式为:

Ki ID1 ID2 IDKi

Ki 是徒弟的个数,后面跟的是各位徒弟的编号,数字间以空格间隔。

Ki为零表示这是一位得道者,这时后面跟的一个数字表示其武功被放大的倍数。

输出:

在一行中输出所有得道者的功力总值,只保留其整数部分。题目保证输入和正确的输出都不超过1010;


思路:树的建立和BFS,在题目中树根已经给出,就是祖师爷,借助队列实现BFS,但要注意n==1的情况


#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const ll maxx = 1e18;
const int N = 1e5+100;
const int pp = 1e4;
const double eps = 1e-8;
struct node{
  vector<int>ve;//存子节点 
  bool flag;//记录是否为得道者 
  double k;//在得道者中记录放大倍数,非得道者中记录徒弟个数 
  double sum;//记录功力值 
}a[N],p; 
int n,cnt,ks,son;//n 总人数 //cnt Ki  //ks 放大倍数 //son 子结点编号   
double z,ss,r,sums;//z 祖师爷功力值 //ss 缩小倍数 // r减弱百分比 //sums 得道者的功力总值 
queue<node>qu;//队列 
int main()
{
  cin>>n>>z>>r;
  if(n==1)
  {
    cin>>cnt>>ks;
    if(cnt==0) 
      cout<<ks*z;
    else
      cout<<"0";
    return 0;
  }//特判 n=1的情况,注意祖师爷本身为得道者的情况 
  ss=(100-r)/100;//算出缩小倍数 
  a[0].sum=z;//存入祖师爷的功力值 
  for(int i=0;i<n;i++)
  {
    cin>>cnt;
    if(cnt==0) 
    {
      cin>>ks;
      a[i].flag=1;
      a[i].k=ks;
    }//得道者做好标记,记录放大倍数(得道者都是叶节点) 
    else
    {
      for(int j=1;j<=cnt;j++)
      {
        cin>>son;
        a[i].ve.push_back(son); 
      }
      a[i].k=cnt;
    }//非得道者记录子节点并且记录子节点总数 
  }
  qu.push(a[0]);//放入根节点 
  while(!qu.empty())
  {
    p=qu.front();
    qu.pop();//取出队首元素 
    if(p.flag==1)
    {
      sums+=p.sum;
    }//得道者加上功力值 
    else
    { 
      for(int i=0;i<p.k;i++)
      {
        if(a[p.ve[i]].flag==1)
        {
          a[p.ve[i]].sum=p.sum*a[p.ve[i]].k*ss;//得道者的功力值一定是衰减后再放大的,注意不要漏掉放大倍数
        }
        else
        {
          a[p.ve[i]].sum=p.sum*ss;
        }
        qu.push(a[p.ve[i]]);
      }
    }//非得道者算出子节点的功力值放入队列,两个注意点 1.vector的下标从 0 开始 2. 先计算出子节点的功力值再压入队列,顺序反了计算无效 
  }
  cout<<(int)sums;//输出功力总值的整数部分 
  return 0; 
}

反思

1.注意得道者的功力值放大前也要衰减,注意细节

2.注意vector的下标从 0 开始,注意细节

3.注意先计算出功力值再进入队列,否则计算无效,注意细节;

4.注意特判 n==1 的情况,注意细节


目录
相关文章
|
6月前
|
存储 算法 搜索推荐
深度优先遍历与广度优先遍历:理解它们的原理与差异
深度优先遍历与广度优先遍历:理解它们的原理与差异
L2-026 小字辈(树的建立+BFS)
L2-026 小字辈(树的建立+BFS)
76 0
|
6月前
|
存储 算法 关系型数据库
【面试普通人VS高手系列】b树和b+树的理解
【面试普通人VS高手系列】b树和b+树的理解
|
存储 关系型数据库 MySQL
浅浅谈一谈B树和B+树
浅浅谈一谈B树和B+树
|
前端开发 算法 API
[LeetCode算法]有了二叉树层序遍历,妈妈再也不用担心我不会做二叉树层级题了
博主最近在刷`leetcode`,做到二叉树套题的时候发现很多题的解题思路都是基于二叉树的层序遍历来完成的,因此写下这篇文章,记录一下二叉树层序遍历这件"神器"在实战的运用。
148 1
|
存储 机器学习/深度学习 Java
《Java数据结构》这些树和二叉树的性质你还记得吗?
《Java数据结构》这些树和二叉树的性质你还记得吗?
120 0
|
机器学习/深度学习 算法
LeetCode——427. 建立四叉树
LeetCode——427. 建立四叉树
88 0
LeetCode——427. 建立四叉树
|
机器学习/深度学习
LeetCode每日一题(13)——建立四叉树(递归)
建立四叉树 1.题目 2.示例 3.思路 4.代码
164 0
LeetCode每日一题(13)——建立四叉树(递归)
|
前端开发
前端知识案例-树的广度优先遍历
前端知识案例-树的广度优先遍历
68 0
前端知识案例-树的广度优先遍历
|
算法 数据库管理
【如何唯一确定一棵二叉树】思想分析及步骤详解
【如何唯一确定一棵二叉树】思想分析及步骤详解
293 0
【如何唯一确定一棵二叉树】思想分析及步骤详解