LUK-Triumphal arch

题目链接:LUK-Triumphal arch


首先考虑二分最小的k。

然后转为判定合法性。我们可以树形dp。

dp[x] 为当前 B 在x点,然后A需要在子树中染色的最小点数。

dp[x] = Σ dp[v]+1 - k

最后判断dp[1]==0即可。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
const int N=3e5+10;
int n,dp[N];
vector<int> g[N];
void dfs(int x,int fa,int mid){
	dp[x]=0;
	for(int to:g[x]) if(to!=fa) dfs(to,x,mid),dp[x]+=dp[to]+1;
	dp[x]=max(0,dp[x]-mid);
}
inline int check(int mid){dfs(1,0,mid); return !dp[1];}
signed main(){
	cin>>n;
	for(int i=1,a,b;i<n;i++) scanf("%d %d",&a,&b),g[a].push_back(b),g[b].push_back(a);
	int l=0,r=n;
	while(l<r){
		int mid=l+r>>1;
		if(check(mid)) r=mid;
		else l=mid+1;
	}
	cout<<l;
	return 0;
}

你可能感兴趣的:(思维题,动态规划,树形dp)