每日一题 day34 打卡
Analysis
这道题的正解本来是树形dp,但要设5个状态,太麻烦了。于是我就用贪心试图做出此题,没想到还真做出来了。
考虑当前深度最大的叶子结点,你肯定要有一个消防局去覆盖它,
那么既然他是叶子结点,所以与他距离小于等于2的节点有这么
- 他的父亲 2. 他的兄弟 3. 他的爷爷
容易看出,在前两项能够覆盖到的节点,在爷爷那里设立一定也能覆盖到。
所以每次贪心取出深度最大的节点,在他的爷爷哪里放一个消防站
用STL的priority_queue,时间复杂度O(nlogn)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #define int long long 8 #define R register 9 #define maxn 1000+10 10 #define rep(i,s,e) for(register int i=s;i<=e;++i) 11 using namespace std; 12 inline int read() 13 { 14 int x=0; 15 bool f=1; 16 char c=getchar(); 17 for(; !isdigit(c); c=getchar()) if(c=='-') f=0; 18 for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+c-'0'; 19 if(f) return x; 20 return 0-x; 21 } 22 inline void write(int x) 23 { 24 if(x<0){putchar('-');x=-x;} 25 if(x>9)write(x/10); 26 putchar(x%10+'0'); 27 } 28 int n,cnt,ans; 29 int head[maxn*maxn],dep[maxn],fa[maxn],book[maxn]; 30 struct node 31 { 32 int v,nex; 33 }edge[2*maxn*maxn]; 34 struct cmp 35 { 36 bool operator () (int &a,int &b) 37 { 38 return dep[a]<dep[b]; 39 } 40 }; 41 priority_queue<int,vector<int>,cmp> q; 42 inline void add(int x,int y) 43 { 44 edge[++cnt].v=y; 45 edge[cnt].nex=head[x]; 46 head[x]=cnt; 47 } 48 void calc_deep(int from,int father,int deep) 49 { 50 dep[from]=deep; 51 fa[from]=father; 52 for(int i=head[from];i;i=edge[i].nex) 53 { 54 int to=edge[i].v; 55 if(to==father) continue; 56 calc_deep(to,from,deep+1); 57 } 58 } 59 void update(int from,int wide) 60 { 61 if(wide>2) return; 62 book[from]=1; 63 for(int i=head[from];i;i=edge[i].nex) 64 { 65 int to=edge[i].v; 66 update(to,wide+1); 67 } 68 } 69 signed main() 70 { 71 n=read(); 72 rep(i,1,n-1) 73 { 74 int x=read(); 75 add(i+1,x);add(x,i+1); 76 } 77 calc_deep(1,0,1); 78 rep(i,1,n) q.push(i); 79 while(!q.empty()) 80 { 81 while(!q.empty()&&book[q.top()]==1) q.pop(); 82 if(q.empty()==1) break; 83 if(fa[fa[q.top()]]==0) update(1,0); 84 else if(fa[fa[q.top()]]>0) update(fa[fa[q.top()]],0); 85 ans++; 86 } 87 write(ans); 88 return 0; 89 }
请各位大佬斧正(反正我不认识斧正是什么意思)