Dynamic Programming Learning on Trees 2 - Another Crisis (Uva12186)

The code is divided into recursive and non-recursive versions.

The recursive version is a direct reference to the purple book.

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
const  int maxn=100000+5;
int n,T;
vector<int> sons[maxn];

int dp(int u) {
    if (sons[u].empty()) return 1;
    vector<int> d;

    for (int i=0; i<sons[u].size(); i++)
        d.push_back(dp(sons[u][i]));

    sort(d.begin(), d.end());
    int c = (sons[u].size()*T-1)/100 + 1;
    int ans = 0;

    for (int i=0; i<c; i++)
        ans+=d[i];

    return ans;
}


int main()
{
    int boss;
    while(scanf("%d%d", &n, &T)==2 && n) {
        for (int i=0; i<=n; i++)
             sons[i].clear();
        for (int i=1; i<=n; i++) {
             scanf("%d", &boss);
             sons[boss].push_back(i);
        }
        cout<<dp(0)<<endl;
    }

    return 0;
}

A few points to note:
1) 
c=(KT-1)/100+1 is the smallest integer representing not less than KT/100. For example, KT=33, then KT/100=0, c=1. KT=1, KT/100=0, c=1.
So why not use KT/100+1 directly? Because if KT/100 is exactly 1, then c=2, but in fact c should be equal to 1.
2) When initializing sons[], i starts from 0, because the boss's sons is also initialized to 0. But when assigning a value to sons[], i starts from 1, such as 0, 3, 5, which means that the boss of employee 1 is 0, the boss of employee 2 is 3, and the boss of employee 3 is 5.
3) Because the title says that the minimum required employee signatures are required, we need to sort the d array to find the first c smallest values.




The non-recursive version was written by me, implemented using stacks. This code may not be optimal because the parent[] array is also added, but it is accepted anyway. If you have a better one, please leave a message.

#include<iostream>
#include<vector>
#include<algorithm>
#include <stack>

using namespace std;
const  int maxn=100000+5;
int n,T;
vector<int> sons[maxn];
int parent[maxn] = {0};

stack<int> s;
int ans[maxn] = {0};

int dp_non_recursion() {
    vector<int> d;

    //从老板开始,依次将儿子压栈
    s.push(0);

    for (int i=0; i<n; i++)
        for (int j=0; j<sons[i].size(); j++)
                s.push(sons[i][j]);

    while(!s.empty()) {
        d.clear();
        int t = s.top();
        s.pop();
        if (sons[t].size()==0)
            ans[t]=1;
        else{
            for (int i=0; i<sons[t].size(); i++) {
                d.push_back(ans[sons[t][i]]);
            }
            sort(d.begin(), d.end());
            int c = (sons[t].size()*T-1)/100 + 1;
            for (int i=0; i<c; i++)
                ans[t]+=d[i];
        }
    }

    return ans[0];
}


int main()
{
    int boss;
    while(scanf("%d%d", &n, &T)==2 && n) {
        for (int i=0; i<=n; i++) {
             sons[i].clear();
             ans[i]=0;
        }
        for (int i=1; i<=n; i++) {
            scanf("%d", &boss);
            parent[i]=boss;
            sons[boss].push_back(i);
        }
        cout<<dp_non_recursion()<<endl;
    }
    return 0;
}

Note that whether recursive or non-recursive, we don't need to use vis[], because each node is processed exactly once, and there is no repeated visit.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325640642&siteId=291194637