可以把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 ", sum); } return 0; }