1106 Lowest Price in Supply Chain (25分)
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 lowest price a customer can expect from some retailers.
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 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:
K**i ID[1] ID[2] … ID[K**i]
where in the i-th line, K**i 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. K**j being 0 means that the j-th member is a retailer. All the numbers in a line are separated by a space.
For each test case, print in one line the lowest price we can expect from some retailers, accurate up to 4 decimal places, and the number of retailers that sell at the lowest price. There must be one space between the two numbers. It is guaranteed that the all the prices will not exceed 1010.
10 1.80 1.00
3 2 3 5
1 9
1 4
1 7
0
2 6 1
1 8
0
0
0
1.8362 2
这道题和1090 正好是相反的,1090要我们求解最大价格,本题要我们求解最小价格。翻译过来就是一个是求解多叉树的最大深度的叶子节点的深度,一个是求解多叉树的最小深度的叶子节点的深度。 因此,本题只需要把 DFS 部分做一点小的调整就可以了。
求解叶子节点的最小深度,我们依然可以使用深度优先遍历。写起来非常简单。每次遍历到叶子节点,就看看这个叶子节点的深度是不是比当前的最小深度还要小,如果比最小深度还小,那么就更新最小深度,同时把最小深度的节点个数num = 1赋值为1 ; 如果当前叶子节点的深度等于当前的最小深度,那么我们又找到了一个最小深度叶子节点,相应的num++ , 否则 当前叶子节点的深度大于当前的最小深度,这不是我们需要的,直接返回。
依然是非常不幸,Java 只通过了3个点 拿到了15分 250ms 不够用…
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
// date:3/17
// 10 1.80 1.00
//3 2 3 5
//1 9
//1 4
//1 7
//0
//2 6 1
//1 8
//0
//0
//0
public class Main {
static class Node {
List<Integer> children = new ArrayList<>();
}
static Node[] nodes ;
static int num =0;
static int minDepth = Integer.MAX_VALUE;
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)) ;
String [] info = bf.readLine().split(" ") ;
int Nodenums = Integer.parseInt(info[0]) ; // 树中节点的个数
double price = Double.parseDouble(info[1]) ; // 初始单价
double r = Double.parseDouble(info[2])/100 ; // 加价幅度,因为输入时%r 需要除以100
nodes = new Node[Nodenums] ;
for(int i = 0 ;i< Nodenums ;i++){
// 读取树的节点信息 行号i就是当前节点ID
nodes[i] = new Node() ;
String [] nodeInfo = bf.readLine().split(" ") ;
int childrenNum =Integer.parseInt(nodeInfo[0]); //孩子个数
if( childrenNum==0)//如果孩子个数为0 进如下一次循环
continue;
else {
for(int j =0 ;j<childrenNum ;j++){
//否则把后面的孩子添加进list
nodes[i] .children.add(Integer.parseInt(nodeInfo[j+1])) ;
}
}
}
DFS(0,0); // 求解,初始root = 0(题目规定的) depth = 0
System.out.printf("%.4f %d" , Math.pow((1+r),minDepth)*price , num);
}
//求解最小深度的叶子节点
static void DFS(int root , int depth ){
if(nodes[root] .children.size() == 0){
if(depth < minDepth ){
num = 1 ;
minDepth = depth ;
}
else if(depth == minDepth){
num ++ ;
}
return;
}
int childrenSize = nodes[root] .children.size() ;
for(int k = 0 ;k<childrenSize ;k++){
DFS(nodes[root].children.get(k) , depth+1);
}
}
}