【HDU4707】Pet(暴搜)

来源:互联网 发布:windows自带图片编辑器 编辑:程序博客网 时间:2024/05/16 17:28

题目链接: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 100010vector<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;}


0 0
原创粉丝点击