洛谷 P2279 消防局的设立(贪心)

题目大意:

已知有一棵树,我们对它进行一个着色操作,每对其中一个节点着色时候,相邻的距离为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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值