黑白树

黑白树

https://ac.nowcoder.com/acm/contest/7/B

此题解与官方题解大概相差不大,甚至代码都大同小异???但也是个人理解,望能帮到你。
为了方便描述,我们先来考虑最简单的树,如图,每个节点最多只有一个子节点。
图片说明
对于这个图我们要怎么染色使得最少呢?
由于每个节点只能由自己染色或由其子节点染色来影响它变成黑色,故显然叶子节点必然要染色。
即给8染上黑色。
现在我们从下往上考虑,设表示从底下往上考虑到第i点时的最少染色数(且保证同染色数最优),最优即越往上影响越多即越优。
现在,,且对8进行染色。这时候都黑了。
现在,到了节点 ,查看一下,已经被染了,所以此时,且都黑了
现在,到了节点,查看一下,没有被染,此时就必须多染一个点,(也许你想调整一下前面的染色??但别忘了,我们cnt的染色方案已经给定位同染色数的最优了),所以如果发现还是白色就必须多染一个点,那为了满足往上染的最多,我们就必须从底部开始选选一个没染色的且往上最多的(这个最多是相对于节点的位置的),有两个点可以选择,那么自然是选择了,所以此时都黑了。


显然且同样都是黑***r>现在来到了节点,同样必须选一个点来染色,即纵观没有染色的(事实上不用分那么多,因为已经染色的没有让节点变黑,所以这些不可能是往上染色最高的)有节点都没有染色,看图,很显然给染色是最好的,因为染了它,直接就可以上到最高点了,此时全都变黑了,任务已经结束了。
所以,你发现贪心策略了吗?
如果能被已经染色的点涂黑,那自然不改变染色。
如果不能,则要从前面找一个染色范围最大的点来染色。
更一般的,对于任意树。
叶子节点一定要染色。
然后从底部往上考虑:若节点已经被染色了,则维持现状。
若节点没被染色,则要从其子节点中找往上覆盖最大范围的点染色,并且更新该节点的最大染色范围。
此过程可以又dfs递归一下便可
代码:

#include<bits/stdc++.h>
#define endl '\n'
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
const int N=1e5+7;
using namespace std;
vector<int>G[N];
int u[N],k[N],cnt;
void dfs(int x)
{
    for(int y:G[x])
    {
        dfs(y);
        u[x]=max(u[x],u[y]-1);//更新到该节点已染色的点的影响范围。
        k[x]=max(k[x],k[y]-1);//更新到该节点的影响范围,即往上可以影响多少个,显然比起子节点少一。
    }
    if(!u[x])//该节点没法被已染色的点影响成黑色,必须多染一个点。
    {
        cnt++;
        u[x]=k[x];//更新该节点的影响范围。
    }
}
int main()
{
  ios::sync_with_stdio(0),cin.tie(0);
  int n;
  cin>>n;
  rep(i,2,n)
  {
    int x;
    cin>>x;
    G[x].emplace_back(i);
  }
  rep(i,1,n)cin>>k[i];
  dfs(1);
  cout<<cnt<<endl;
}
全部评论

相关推荐

粗心的雪碧不放弃:纯学历问题,我这几个月也是一直优化自己的简历,后来发现优化到我自己都觉得牛逼的时候,发现面试数量也没有提升,真就纯学历问题
点赞 评论 收藏
分享
ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
2 1 评论
分享
牛客网
牛客企业服务