PAT-1079 Total Sales of Supply Chain (树的遍历)
1079. Total Sales of Supply
A supply chain is a network of retailers(零售商), distributors(经销商), and suppliers(供应商)-- everyone involved in moving a product from supplier to customer.
Starting from one root supplier, everyone on the chain buys products from one's supplier in a price P and sell or distribute them in a price that is r% higher than P. Only the retailers will face the customers. It is assumed that each member in the supply chain has exactly one supplier except the root supplier, and there is no supply cycle.
Now given a supply chain, you are supposed to tell the total sales from all the retailers.
Input Specification:
Each input file contains one test case. For each case, the first line contains three positive numbers: N (<=105), the total number of the members in the supply chain (and hence their ID's are numbered from 0 to N-1, and the root supplier's ID is 0); P, the unit price given by the root supplier; and r, the percentage rate of price increment for each distributor or retailer. Then N lines follow, each describes a distributor or retailer in the following format:
Ki ID[1] ID[2] ... ID[Ki]
where in the i-th line, Ki is the total number of distributors or retailers who receive products from supplier i, and is then followed by the ID's of these distributors or retailers. Kj being 0 means that the j-th member is a retailer, then instead the total amount of the product will be given after Kj. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print in one line the total sales we can expect from all the retailers, accurate up to 1 decimal place. It is guaranteed that the number will not exceed 1010.
Sample Input:10 1.80 1.00
3 2 3 5
1 9
1 4
1 7
0 7
2 6 1
1 8
0 9
0 4
0 3
Sample Output:
42.4
题目大意:给出一颗由商品供应关系构成的树,最初的供应商即为树的根节点,要求计算所有零售商(即树的叶子节点)的销售额。题目首先给出三个常数,n(树的节点数),p(初始价格),r(每出售一次的增长率),然后按照节点
id 的顺序输入n行。首先输入一个整数k,如果 k>0,那么紧随其后的是该节点的k个子节点;如果k=0,则表示该节点是叶子节点,接着给出该节点的销售商品数量。
主要思想:1. 最直接的想法就是在接受输入时用一个数组保存每个节点的父节点,当遇到叶子节点时用容器保存该节点的id 及销售量信息。然后对于容器中的所有叶子节点,求出它们的深度(经历了几次涨价),然后求出销售总额。需要注意的是在求深度的时候应该用数组保存每个求出的节点的深度,这样求未知节点时可以利用这些数据来节约时间,否则有些用例会超时。
#include <cstdio> #include <iostream> #include <cmath> #include <vector> using namespace std; typedef struct { int id; //经销商的id int num; //商品数量 } retailer; int father[100000]; //该节点的父节点 int level[100000]; //该节点所处层数 int get_level(int id); int main(void) { int n, i, j; double p, r; vector<retailer> vec; vector<retailer>::iterator iter; cin >> n >> p >> r; int k, num, id; for (i = 0; i < n; i++) { cin >> k; if (k == 0) { cin >> num; retailer re; re.id = i; re.num = num; vec.push_back(re); } else { for (j = 0; j < k; j++) { cin >> id; father[id] = i; } } } double total = 0;; for (iter = vec.begin(); iter != vec.end(); iter++) { /* //开始用从每个叶子节点迭代回根节点求深度,会超时 int count = 0; for (i = iter->id; i != 0; i = father[i]) count++; total += (iter->num) * p * pow(1 + r/100, count); */ total += (iter->num) * p * pow(1 + r/100, get_level(iter->id)); } printf("%.1f\n", total); return 0; } //获取节点的层数 int get_level(int id) { if (id == 0) return 0; if (level[id] == 0) level[id] = get_level(father[id]) + 1; return level[id]; }
2.此题还可以利用 dfs 或 bfs 来对树进行遍历,利用结构体的数组来储存所有节点,类似于图的邻接表表示法。
typedef struct { int num; //如果是叶子节点,则表示销售量 vector<int> child; //该节点的所有子节点 } node; vector<node> v; //树中节点的集合
在使用dfs的时候可以将深度作为递归函数的参数,则可以很方便求出每一个叶节点的深度,并在递归中累加出总销售额。
dfs(0, 0); void dfs(int id, int depth) { if (v[id].child.size() == 0) { //表明是叶子节点 sum += v[id].num * p * pow(1 + r/100, depth); return; } for (int i = 0; i < v[id].child.size(); i++) dfs(v[id].child[i], depth + 1); //进入下一层深度加1 return; }