zoukankan      html  css  js  c++  java
  • P3554 [POI2013]LUK-Triumphal arch 题解

    P3554 [POI2013]LUK-Triumphal arch 题解

    间隙

    知识点

    • 树形(DP) , 二分答案

    分析

    题意翻译里已经写的很清楚了,这里就不重复一遍了

    首先这里的答案(k)具有可二分性,考虑二分答案

    (B)走到一个节点(u)时,第一步要做的肯定是把(u)的儿子全部都涂色

    如果一个节点的儿子数大于当前的(k),则无论怎么涂都会输

    反之,说明除了涂自己的儿子外还可以"提前"涂其他的节点

    (f[i])为以(i)根节点的子树需要其祖先"提前"染色多少个点才能覆盖整个子树

    易得状态转移方程:(f[u] = max(0 , sum f[v]+1-k))

    具体解释(:)

    代码实现

    直接二分答案(k),对于每一个(k)进行(dp)

    如果(f[1])(0),则说明可行

    反之说明不可行

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 3e5+10;
    int n;
    struct e{
    	int to,next;
    }edge[MAXN<<1];
    int head[MAXN<<1],cnt = 0;
    int f[MAXN];
    void add(int u,int v){//前向星
    	edge[++cnt].to = v;
    	edge[cnt].next = head[u];
    	head[u] = cnt;
    }
    void dfs(int u,int fa,int k){
    	int sum = 0;
    	for(int i=head[u];i;i=edge[i].next){
    		int v = edge[i].to;
    		if(v==fa) continue;
    		dfs(v,u,k);
    		sum=sum+f[v]+1;//记录
    	}
    	f[u] = max(0,sum-k);
    }
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n-1;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		add(u,v);
    		add(v,u);
    	}
    	int l = 0,r = 10e10;
    	int ans = -1;
    	while(l<=r){//二分答案
    		memset(f,0,sizeof(f));
    		int mid = (l+r)>>1;
    		dfs(1,0,mid);//dp
    		if(f[1]==0){//如果f[1]为0 说明可行
    			ans = mid;
    			r = mid-1;
    		}反之,不可行
    		else l = mid+1;
    	}
    	printf("%d",ans);
    }
    
  • 相关阅读:
    mac上finalShell的安装
    c 字符串与字符串操作
    .net5 MailKit
    c 99乘法表
    element 动态表单加自定义校验
    遇到的问题 vscode 问题
    vue-element-admin eslint 规则查询表
    利用html2canvas 导出网页 (只是用于自己的笔记,如果需要看配置,自行查找插件api)
    git 常用命令
    uniapp中自动打包微信小程序后自动上传代码
  • 原文地址:https://www.cnblogs.com/xcxc82/p/13536223.html
Copyright © 2011-2022 走看看