zoukankan      html  css  js  c++  java
  • 【CF】【 树形DP】F. Zublicanes and Mumocrates

    树形DP

    树形dp大体结构

    void dfs(int u,int fa)
    {
         是否为叶子结点
            如果是的话,就执行一些底层的信息的记录
         如果不是
            遍历结点u所有连接的边,并取出对应的端点
            如果端点是父亲结点
               continue;
    }
    

    参数列表里面不单含有当前这个结点,还包括当前这个结点的父亲结点,这是为了避免在遍历u所连接的结点的时候出现冲突。

    image

    f[i][j][0/1]代表的是第i结点被染上颜色0/1并且具有j个叶子结点被染上颜色1的存在两个端点异色的边的最少边数

    题目要求的是,当叶子结点对半染不同的颜色,所以最终要求的是整棵树内最少要求的边数。

    min(f[root][total/2][0],f[root][total/2][1])

    total记录的是叶子结点的个数。

    #include <bits/stdc++.h>
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define W(a) while(a)
    #define gcd(a,b) __gcd(a,b)
    #define pi acos(-1.0)
    #define PII pair<int,int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define ull unsigned long long
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define MAX 1000005
    #define MOD 1000000007
    #define INF 0x3f3f3f3f
    #define lowbit(x) (x&-x)
    using namespace std;
    const int N = 5E3+10,M=1E4+100;
    int h[N],ne[M],e[M],idx;
    void add(int a,int b)
    {
    	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    int f[N][N][2],g[N][2],sons[N],n,m,du[N];
    void dfs(int u,int fa)
    {
    	if(du[u]==1)
    	{
    		sons[u]=1;
    	    f[u][1][1]=0,f[u][0][0]=0;
    		return ;
    	}
    	f[u][0][0]=0,f[u][0][1]=0;//此时u结点没有连上任何结点,相当于是一种断联的状态 
    	for(int i=h[u];~i;i=ne[i])
    	{
    		int j=e[i];
    		if(j==fa) continue;
    		
    		dfs(j,u);
    		memset(g,0x3f,sizeof(g));
    		for(int k=0;k<=sons[u];k++)//未加入儿子结点j所拥有的状况 
    		{
    			//由已知量扩展到未知量 
    			for(int kk=0;kk<=sons[j];kk++)
    			{
    				g[k+kk][0]=min(g[k+kk][0],f[u][k][0]+f[j][kk][1]+1);
    				g[k+kk][0]=min(g[k+kk][0],f[u][k][0]+f[j][kk][0]);
    				g[k+kk][1]=min(g[k+kk][1],f[u][k][1]+f[j][kk][0]+1);
    				g[k+kk][1]=min(g[k+kk][1],f[u][k][1]+f[j][kk][1]);
    			}
    		}
    		for(int k=0;k<=sons[u]+sons[j];k++)
    		   for(int kk=0;kk<2;kk++)
    		       f[u][k+kk][0]=g[k+kk][0],f[u][k+kk][1]=g[k+kk][1];
    		sons[u]+=sons[j];
    	}
    }
    
    int main()
    {
    	memset(h,-1,sizeof(h));
    	memset(f,0x3f,sizeof(f));
    	scanf("%d",&n);
    	for(int i=1;i<=n-1;i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		add(x,y);add(y,x);
    		du[x]++,du[y]++;
    	}
    	int ones=0,root;
    	for(int i=1;i<=n;i++)
    	    if(du[i]==1) 
    	      ones++;
    	    else 
    	      root=i;
    	dfs(root,-1);
    	cout<<min(f[root][ones/2][0],f[root][ones/2][1]);
        return 0;
    }
    
    

    其他

    • 在一颗树里面,只要一个结点的度大于等于2,就有资本去作为,一棵树的根节点(可以调换)。

    • 叶子结点度为1

    • C库函数memcpy

      C 库函数 void memcpy(void str1, const void str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1

      memcpy(dst,ori+pos,num)

      代表是的是从ori中第pos的位置(包括pos这个位置上的内容),连续赋值num个内容过去给dst.

    树状DP的精髓

    假设一个结点有n个儿子结点,那么在DP的过程中会先去计算一部分,然后其他的会站在已经计算了的基础上再做DP。

  • 相关阅读:
    Docker部署Tomcat
    Docker部署MySQL
    kettle 共享数据库连接(解决每次都需要创建数据库连接问题)
    Kettle8.2的安装与使用
    Kettle 使用JS脚本 增加UUID输出列
    kettle使用(mysql导入MongoDB)
    Eclipse从Git上下载代码
    Eclipse中使用git
    在windows下安装git中文版客户端并连接gitlab
    eclipse中git的安装、配置和使用
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15320590.html
Copyright © 2011-2022 走看看