【HDU4707】Pet(暴搜)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4707

题意:一棵树有n个结点,编号从0到n-1,每条边的距离视为1,求与0号结点距离大于d的结点个数。

思路:题目所给n的范围是<=1e5,根据题意,方法应该为从0号结点开始,暴力搜索出与0号结点距离小于等于d的结点个数cnt,然后输出n-cnt即可。接下来是搜索的实现部分,首先选择是DFS还是BFS,分析发现选择任一种均可。然后是图的存储方法,由于n的规模较大不能使用邻接矩阵(O(n^2),会MLE)存储,所以采用邻接表(O(n+e)即2*n不会MLE)存储。但传统数据结构中的邻接表需要维护指针,实现较为复杂,可以考虑使用STL中的vector代替。

这里需要用到vector的一些方法:

  1. vector::push_back()  将元素加入到向量
  2. vector::clear()  将向量清空
  3. vector::size()  返回向量中元素个数

此外vector也支持下标法检索元素,掌握了这些方法即可熟练使用它作为图的邻接表,省去了自己实现可变长向量的麻烦,且效果很好。 存储问题解决后,BFS或DFS就比较容易实现了,这里仅提供一种BFS的实现方法:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
using namespace std;

#define MAXN 100010
vector<int> mp[MAXN];
bool vis[MAXN];
int n, d, cnt;

void init(){
    for(int i=0; i<MAXN; i++) mp[i].clear();
    memset(vis, false, sizeof vis);
    cnt = 0;
}

struct NODE{
    int id;
    int step;
};

void bfs(){
    queue<NODE> Q;
    NODE st;
    st.id = st.step = 0;
    vis[0] = true;
    cnt++;
    Q.push(st);
    while(!Q.empty()){
        NODE now = Q.front();
        Q.pop();
        if(now.step > d) break; //剪枝
        printf("***to node %d\n", now.id);
        int len = mp[now.id].size();
        for(int i=0; i<len; i++){
            if(vis[mp[now.id][i]] == false){
                vis[mp[now.id][i]] = true;
                NODE next;
                next.id = mp[now.id][i];
                next.step = now.step + 1;
                Q.push(next);
                if(next.step <= d) cnt++;
            }
        }
    }
}

int main()
{
    int T, x, y;
    cin >> T;
    while(T--){
        init();
        scanf("%d %d", &n, &d);
        for(int i=0; i<n-1; i++){
            scanf("%d%d", &x, &y);
            mp[x].push_back(y);
            mp[y].push_back(x);
        }
        bfs();
        printf("%d\n", n - cnt);
    }
    return 0;
}

点赞