洛谷P2279 [HNOI2003]消防局的设立(深搜,贪心)

针对火星基地群的特殊结构,采用深搜与贪心算法确定消防局的最佳布局方案,确保每个基地都能得到及时的火灾救援。

洛谷P2279 [HNOI2003]消防局的设立(深搜,贪心)

题目描述

2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地。起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d。
由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾。
你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。

输入输出格式

输入格式:

输入文件的第一行为n (n<=1000),表示火星上基地的数目。接下来的n-1行每行有一个正整数,其中文件第i行的正整数为a[i],表示从编号为i的基地到编号为a[i]的基地之间有一条道路,为了更加简洁的描述树状结构的基地群,有a[i]<i。

输出格式:

输出文件仅有一个正整数,表示至少要设立多少个消防局才有能力及时扑灭任何基地发生的火灾。

输入输出样例

输入样例#1:

6
1
2
3
4
5

输出样例#1:

2

解题分析

以1为根节点,依次从深度较大的结点出发,采用贪心算法。
步骤:
1、从结点1出发,进行深搜,确定每一个结点的深度,并由此确定每一个结点的父节点和爷结点,其中结点1的根节点为1。
2、按深度从小到达对结点进行排序。
3、按照上述顺序,搜索当前还没有染色的结点,将其爷结点建一个消防局(结果加1),并将离该结点距离为不大于2的结点染色。

4、直到所有结点都染色。

小坑:输入时,第一条道路的起点为2,第二条道路的起点为3,......

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define N 1002
int n, head[N], tot = 0, used[N]= {0};

struct node {
    int to;
    int next;
    node():next(-1) {
    }
} e[2*N];

struct node1 {
    int index;
    int dep;
    int parent;
    int gf;
    node1():parent(0) {
    }
    void set(int i, int d, int p) {
        index = i;
        dep = d;
        parent = p;
    }
} depth[N];

void get_i(int &x) {
    char ch = getchar();
    x = 0;
    while(!isdigit(ch)) ch = getchar();
    while(isdigit(ch)) {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
}

void add_e(int from, int to) {
    e[tot].to = to;
    e[tot].next = head[from];
    head[from] = tot++;
}

bool cmp(node1 n1, node1 n2) {
    return n1.dep > n2.dep;
}

void dfs(int from, int dep) {
    int i, to;
    used[from] = 1;
    for(i=head[from]; ~i; i=e[i].next) {
        to = e[i].to;
        if(used[to])
            continue;
        depth[to].set(to, dep+1, from);
        dfs(to, dep+1);
    }
}

void change(int k) {
    int i, to;
    queueq;
    for(i=head[k]; ~i; i=e[i].next) { // 与k的距离等于1的结点染色
        to = e[i].to;
        used[to] = 1;
        q.push(to);
    }
    while(!q.empty()) {	// 与k的距离等于2的结点染色
        to = q.front();
        q.pop();
        for(i=head[to]; ~i; i=e[i].next)
            used[e[i].to] = 1;
    }
}

int main() {
    ios::sync_with_stdio(false);
    int i, to, gf, ans = 0;
    memset(head, -1, sizeof(head));
    get_i(n);
    for(i=1; i

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值