1. 程式人生 > >[HNOI2003]消防局的設立

[HNOI2003]消防局的設立

operator string 文件的 name AC 描述 tin main gpo

題目描述

2020年,人類在火星上建立了一個龐大的基地群,總共有n個基地。起初為了節約材料,人類只修建了n-1條道路來連接這些基地,並且每兩個基地都能夠通過道路到達,所以所有的基地形成了一個巨大的樹狀結構。如果基地A到基地B至少要經過d條道路的話,我們稱基地A到基地B的距離為d。

由於火星上非常幹燥,經常引發火災,人類決定在火星上修建若幹個消防局。消防局只能修建在基地裏,每個消防局有能力撲滅與它距離不超過2的基地的火災。

你的任務是計算至少要修建多少個消防局才能夠確保火星上所有的基地在發生火災時,消防隊有能力及時撲滅火災。

輸入輸出格式

輸入格式:

輸入文件名為input.txt。

輸入文件的第一行為n (n<=1000),表示火星上基地的數目。接下來的n-1行每行有一個正整數,其中文件第i行的正整數為a[i],表示從編號為i的基地到編號為a[i]的基地之間有一條道路,為了更加簡潔的描述樹狀結構的基地群,有a[i]<i。

輸出格式:

輸出文件名為output.txt

輸出文件僅有一個正整數,表示至少要設立多少個消防局才有能力及時撲滅任何基地發生的火災。

輸入輸出樣例

輸入樣例#1: 復制
6
1
2
3
4
5
輸出樣例#1: 復制
2


【題解】貪心。對於每一個最深的節點都去父親那更新

#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int N=1010,M=2200;
int ver[M<<1
],head[N],nxt[M<<1],en,d[N],fa[N]; inline void AddEdge(int from,int to) { ver[++en]=to,nxt[en]=head[from],head[from]=en; } bool v[N]; void dfs(int x,int pre) { fa[x]=pre; d[x]=d[pre]+1; v[x]=true; for(int i=head[x]; i; i=nxt[i]) { int y=ver[i]; if(v[y])continue
; dfs(y,x); } } struct cmp{ bool operator()(int &x,int &y){ return d[x]<d[y]; } }; void update(int x,int depth){ if(depth>2)return ; v[x]=true; for(int i=head[x];i;i=nxt[i]) update(ver[i],depth+1); } int main() { int n,to; scanf("%d",&n); for(int i=2; i<=n; i++) { scanf("%d",&to); AddEdge(to,i); AddEdge(i,to); } memset(d,0,sizeof(d)); memset(v,0,sizeof(v)); dfs(1,0); priority_queue<int,vector<int>,cmp > Q; for(int i=1;i<=n;i++)Q.push(i); memset(v,0,sizeof(v)); int ans=0; while(!Q.empty()){ int u=Q.top();Q.pop(); if(!v[u]){ update(fa[fa[u]],0); ans++; } } printf("%d\n",ans); return 0; }

[HNOI2003]消防局的設立