一、题目详情
输入解释
- 第一行输入三个正整数,N、P、r,N为树中的元素个数,P为树根处的货物价格,r为每走一层货物价格的上涨比率r%(变为父节点价格的(1+r%)倍)
- 下面1行依次输入1~N号结点的父节点编号(根节点则输入-1)
输出解释
输出两个数字,以空格分隔,分别是:能得到的最大价格(精度为两位小数) 具有最大价格的节点个数
思路
- 将供销商问题抽象成树,因为题中说可以保证每一个节点都只有一个供应来源,并且供应链中没有环,所以这个抽象过程应该还是挺明显的~
- 要理解求最大价格实际就是求树的深度,一般用DFS来获取树的最大深度,那么写dfs函数时就需要把当前深度作为一个参数,还需要将下标作为一个参数。函数形式为DFS(int index,int depth)。
- 递归边界是到达叶节点,也就是子节点数为0,每次都需要进行判断。
- 递归式是通过访问该节点的每一个子节点,同时当前深度加一。
- 在本题中树的结构比较简单,不涉及到权重等,只需要记录节点编号这一信息,所以不妨开一个vector型数组,以节点编号作为下标,用vector来存放每一个节点的子节点编号。
二、实现代码
算法笔记中用了DFS
#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
const int maxn = 10005;
vector<int> child[maxn];
int maxdepth; //最大深度
int n;
double p,r;
int num; //深度为最大的节点个数
void DFS(int index,int depth)
{
//递归边界
if(child[index].size()==0) //到达叶节点
{
if(depth>maxdepth) //如果当前深度大于最大深度,则更新最大深度,并将num置1
{
maxdepth=depth;
num=1;
}
//当前深度等于最大深度,则深度最大的节点个数++
else if(depth==maxdepth) num++;
//记得是else if而不是if!!因为上一步设置了maxdepth=depth,写为if的话会执行num++
return ;
}
for(int i=0;i<child[index].size();i++)
{
DFS(child[index][i],depth+1); //递归式
}
}
int main()
{
int root,t;
scanf("%d%lf%lf",&n,&p,&r);
r /= 100;
for(int i=0;i<n;i++)
{
scanf("%d",&t);
if(t!=-1) child[t].push_back(i);
else root = i;
}
DFS(root,0);
printf("%.2f %d",p*pow((1+r),maxdepth),num);
}
BFS实现
#include<iostream>
#include<vector>
#include<queue>
#include<math.h>
using namespace std;
const int maxn = 100005;
vector<int> child[maxn];
int d[maxn]; //d[i]为每个节点的深度
int maxdepth;
int n;
double p,r;
int num=0;
int main()
{
int root,t;
scanf("%d%lf%lf",&n,&p,&r);
r /= 100;
for(int i=0;i<n;i++)
{
scanf("%d",&t);
if(t!=-1) child[t].push_back(i);
else root = i;
}
queue <int> q;
q.push(root);
while(!q.empty())
{
t = q.front();
q.pop();
for(int i=0;i<child[t].size();i++)
{
d[child[t][i]] = d[t]+1;
if(maxdepth<d[child[t][i]]) //更新操作
maxdepth = d[child[t][i]];
q.push(child[t][i]);
}
}
//已经得到最大深度maxdepth,通过遍历d数组来找出节点为maxdepth的节点个数
for(int i=0;i<n;i++)
if(d[i]==maxdepth) num++;
printf("%.2f %d",p*pow((1+r),maxdepth),num);
}