Hdu 5326 Work

  可以把N个人分别看作顶点,各种关系则看作边,因为边数正好是N-1,结合题目,其实可以证明这是一棵树。题目要求的就是计算结点数(不包括根)的为K的子树有多少棵。

  建立一棵树,然后一个结点 i 为根的子树的结点数,就是 i 的直接相连的结点,以及以它直接相连的结点为根的子树的结点数。如果没有子结点,则放回0。因为有些结点会重复访问,且没必要重新计算,因此可以将其结果保存,避免重复计算。

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>

using namespace std;

const int MAXN = 100 + 50;
std::vector<int> link[MAXN];
int manage[MAXN];
int N, K;

void Init() {
    for(int i=1; i<=N; i++) {
        link[i].clear();
        manage[i] = -1;
        // -1 代表此结点尚未被访问
    }
}

void Read() {
    int x, y;
    for(int i=0; i<N-1; i++) {
        scanf("%d%d", &x, &y);
        link[x].push_back(y);
    }
}

int Count(int ser) {
    if(manage[ser]!=-1) {
        // 已经访问过此结点,直接返回结果即可
        return manage[ser];
    }
    if( link[ser].size() == 0 ) {
        // 叶子结点
        return manage[ser] = link[ser].size();
    } else {
        int sum = 0;
        for(size_t i = 0; i<link[ser].size(); i++) {
            sum += Count(link[ser][i]);
        }
        return manage[ser] = link[ser].size() + sum;
    }
}

int main() {
    while(cin >> N >> K) {
        Init();
        Read();
        int sum = 0;
        for(int i=1; i<N+1; i++) {
            if( Count(i) == K ) {
                sum ++;
            }
        }
        printf("%d\n", sum);
    }
    return 0;
}

 

posted @ 2015-08-03 19:52  Emerald  阅读(156)  评论(0编辑  收藏  举报