zoukankan      html  css  js  c++  java
  • hiho challenge 15 C题

    DP题。状态很容易设,dp[u][0]表示u点子树解决,dp[u][1]表示剩一条链,dp[u][2]表示邻边全炸.

    转移有点难,看代码解释:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    const int MAX=100005;
    
    vector<int>t[MAX];
    int dp[MAX][3];
    
    
    void dfs(int u,int f){
    	dp[u][0]=dp[u][1]=dp[u][2]=0;
    	int sz=t[u].size(),v,counts=0,s=0;
    	for(int i=0;i<sz;i++){
    		v=t[u][i];
    		if(v!=f){
    			dfs(v,u);
    		}
    		else continue;
    		s+=min(min(dp[v][0],dp[v][1]),dp[v][2]);
    		if(dp[v][2]>min(dp[v][0],dp[v][1])){////dp[v][2]>min(dp[v][0],dp[v][1])这种情况表示选择不是全炸的,否则全炸,因为全炸的话,就不需要再多一次操作了。除非不是
    		///全炸的更少,因为如果更少,则dp[v][2]至少大1
    			counts++;///统计有多少个是儿子节点不是子邻边全炸的,这样每两个儿子节点就可以使用一次解决。
    		}
    		dp[u][2]+=dp[v][0];///邻边全炸,肯定是要儿子节点的子树全部解决。
    	}
    	dp[u][0]+=s+counts/2+((counts%2)?1:0);///如果有奇数个儿子节点不是邻边全炸,就/2后,需要一次和根节点的操作才可以全解决,偶数则不需要
    	dp[u][1]+=s+counts/2;////剩一条链也不需要加上一次操作
    	dp[u][2]++;
    }
    
    int main(){
    	int n,u,v;
    	while(scanf("%d",&n)!=EOF){
    		for(int i=1;i<=n;i++) t[i].clear();
    		for(int i=1;i<n;i++){
    			scanf("%d%d",&u,&v);
    			t[u].push_back(v);
    			t[v].push_back(u);
    		}
    		dfs(1,0);
    		printf("%d
    ",min(dp[1][2],dp[1][0]));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    TCP与UDP的区别
    gdb调试入门(上)
    linux开发工具之Makefile(上)
    在kolla中配置cinder ceph多后端
    OpenStack qemu-guest-agent 使用
    Windows 环境下使用强大的wget工具
    Centos 7 GCC 7.3编译器安装方法及C++17标准测试示例
    Neutron 架构图
    openstack 的 lbaas 疑问
    Mounting VMDK files in Linux
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4886405.html
Copyright © 2011-2022 走看看