PAT1079 Total Sales of Supply Chain (25)(dfs,树的遍历)

题目

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,非叶子节点之间有边权(1+r),叶子节点有权重Kj,输出最后的总权值
分析题目:用结构体数组完成数据结构,dfs遍历

代码

#include <iostream>
#include <vector>
#include <cmath>
#include <cstdio>
using namespace std;

struct node{
    bool isRetailer;
    int productAmount;
    int childNum;
    vector<int> child;
};

vector<node> tree;

double result = 0.0;
double P, r;

void dfs(int root, int depth)
{
    if(tree[root].isRetailer)
    {
        result += tree[root].productAmount*(pow(1+r/100,depth));
        return;
    }
    for(int i = 0; i<tree[root].childNum; i++)
    {
        dfs(tree[root].child[i], depth+1);
    }
}

int main()
{
    int N;

    cin >> N >> P >> r;
    tree.resize(N);
    for(int i = 0; i<N; i++)
    {
        int Ki;
        cin >> Ki;
        if(!Ki)
        {
            tree[i].isRetailer = true;
            cin >> tree[i].productAmount;
        }
        else
        {
            tree[i].isRetailer = false;
            tree[i].childNum = Ki;
            tree[i].child.resize(Ki);
            for(int j = 0; j<Ki; j++)
                cin >> tree[i].child[j];
        }
    }
    dfs(0,0);
    printf("%.1f", result*P);
    return 0;
}

总结

dfs题目做多了之后,这道题思路相对比较清晰了
在调试的时候命名起了冲突,题目的r和dfs函数常用的根节点变量r冲突了,以后命名根节点的时候用root,同时看题的时候要注意题目的变量是否和常用的变量冲突。

PAT 1094. The Largest Generation (25)-(bfs,dfs,树的遍历)

题目

A family hierarchy is usually presented by a pedigree tree where all the nodes on the same level belong to the same generation. Your task is to find the generation with the largest population.

Input Specification:

Each input file contains one test case. Each case starts with two positive integers N (<100) which is the total number of family members in the tree (and hence assume that all the members are numbered from 01 to N), and M (<N) which is the number of family members who have children. Then M lines follow, each contains the information of a family member in the following format:

ID K ID[1] ID[2] … ID[K]

where ID is a two-digit number representing a family member, K (>0) is the number of his/her children, followed by a sequence of two-digit ID’s of his/her children. For the sake of simplicity, let us fix the root ID to be 01. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print in one line the largest population number and the level of the corresponding generation. It is assumed that such a generation is unique, and the root level is defined to be 1.

Sample Input:
23 13
21 1 23
01 4 03 02 04 05
03 3 06 07 08
06 2 12 13
13 1 21
08 2 15 16
02 2 09 10
11 2 19 20
17 1 22
05 1 11
07 1 14
09 1 17
10 1 18
Sample Output:
9 4

分析题目

  • 查单词: pedigree tree谱系树(就是一颗树)
  • 题目大意:遍历数组,计算树中一层中最大的节点个数以及当前层数
  • 分析:用二维数组完成数据结构,分别用dfs和bfs两种方法都可以实现遍历。dfs的话用一个数组level[l]记录当前l层的节点数,最后取最大值。

代码

#include <iostream>
#include <vector>

using namespace std;

vector<int> tree[105];
int level[100];
int N, M;

void dfs(int root, int cLevel)
{
    level[cLevel]++;
    for(int i = 0; i<tree[root].size(); i++)
        dfs(tree[root][i], cLevel+1);
}

int main()
{
    cin >> N >> M;
    for(int i = 0; i<M; i++)
    {
        int ID, childNum;
        cin >> ID;
        cin >> childNum;
        tree[ID].resize(childNum);
        for(int j = 0; j<childNum; j++)
        {
            cin >> tree[ID][j];
        }
    }
    dfs(1,1);
    int maxPopulation = 0;
    int generation = 1;
    for(int i = 1; i<100; i++)
    {
        if(maxPopulation < level[i])
        {
            maxPopulation = level[i];
            generation = i;
        }
    }
    cout << maxPopulation << " " << generation;
    return 0;
}

总结

  1. 刚开始用了结构体数组去构建数据结构,但是由于节点数为0的节点没有进行任何的初始化,导致内存访问出错,pat上出现的错误为段错误
    错误代码:
#include <iostream>
#include <vector>
using namespace std;

struct node{
    int childNum;
    vector<int> child;
};

vector<node> tree;
vector<int> level;
int N,M;

void dfs(int root, int l)
{
    if(tree[root].childNum == 0)
    {
        level[l]++;
        return;
    }
    for(int i = 0; i<tree[root].child.size(); i++)
    {
        dfs(tree[root].child[i], l+1);
    }
    level[l]++;
}

int main()
{
    cin >> N >> M;
    level.resize(N);
    tree.resize(N);
    ```想尝试用下面这种方式去初始化树,但也无济于事,有点没太懂```
//    node example;
//    example.childNum = 0;
//    example.child.resize(example.childNum, 0);
//    tree.resize(N, example);
//    cout << tree[23].childNum << endl;   
    for(int i = 0; i<M; i++)     ```这里只是把非叶子节点给初始化了,叶子节点内存不知道该分配到哪
    {
        int ID;
        cin >> ID;
        cin >> tree[ID].childNum;
        tree[ID].child.resize(tree[ID].childNum, 0);
        for(int j = 0; j<tree[ID].childNum; j++)
        {
            cin >> tree[ID].child[j];
        }
    }
    dfs(1, 1);
    int largestPopulation = 0;
    int generation = 0;
    for(int i = 1; i<N; i++)
    {
        if(level[i]>largestPopulation)
        {
            largestPopulation = level[i];
            generation = i;
        }
        if(!level[i])
            break;
    }
    cout << largestPopulation << " " << generation;
    return 0;
}
  1. 这题可以和pat1053 对比看,1053里面对叶子节点有初始化,所以用结构体数组是妥妥没问题的。
  2. 如果树的结构相对简单,没有点权值、边权值,只是指向了子节点,一般可以考虑用二维数组构建数据结构
  3. 小错误
    在对level求解的时候,容易犯两个错误,
    for(int i = 0; i<100;i++)这里是i从0开始遍历了,但0层是没东西的,也无伤大雅,调试能过
    for(int i = 1; i<N; i++)如果有N个节点,最大是有N层,这里从1~N只遍历了N-1层,如果改成N+1就没有问题了
for(int i = 1; i<100; i++)
    {
        if(maxPopulation < level[i])
        {
            maxPopulation = level[i];
            generation = i;
        }
    }
  1. 二话不说,贴柳神代码
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章