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. 二話不說,貼柳神代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章