题目大意:
已知有一棵树,我们对它进行一个着色操作,每对其中一个节点着色时候,相邻的距离为2的节点也会同时着色,问我们最少需要的着色次数是多少。
解题思路:
使用贪心,我们从树的深度从深到浅遍历节点。节点若还未染色,我们则对它的爷爷进行染色。为什么这样染色是可行的呢?因为这样染色我们可以把它,它的兄弟,它的父亲全部进行着色而且还能向外拓展。
问题是:怎么知道这个节点染了色没有,我们假若对每一个节点染色后进行模拟,可能会T,视乎图的结构。这里我们维护一个数组o[i],表示离i节点最近的染色点的距离,每次我们更新o[i]的时候
o[i]=min(o[fahter]+1,o[i],o[grandfather]+2)
在进行染色的时候
o[grandfather]= 0
o[ parent[grandfather]] = min ( o[ parent[grandfather]] ,1 )
o[ parent[parent[grandfather]] ] = min ( o[ parent[parent[grandfather]] ] ,2 )
#include <bits/stdc++.h>
using namespace std;
const int INF=2010;
int main(){
int n;cin>>n;
vector<pair<int,int>> gra;
int dist[n];
int prt[n];
int o[n];
for(int i=0;i<n;i++)o[i]=INF;
dist[0]=0;
gra.push_back(make_pair(0,1));
prt[0]=0;
for(int i=1;i<n;i++){
int t;cin>>t;t-=1;
dist[i]=dist[t]+1;
prt[i]=t;
gra.push_back(make_pair(dist[i],i));
}
sort(gra.begin(),gra.end(),greater<pair<int,int>>());
int ans=0;
for(auto it:gra){
//cerr<<it.second<<endl;
int u=it.second;
int fath=prt[u];
int gran=prt[fath];
o[u]=min(o[u],min(o[fath]+1,o[gran]+2));
//cerr<<o[u]<<endl;
if(o[u]>2){
o[gran]=0;ans++;
o[prt[gran]]=min(o[prt[gran]],1);
o[prt[prt[gran]]]=min(o[prt[prt[gran]]],2);
}
}
cout<<ans<<endl;
return 0;
}