zoukankan      html  css  js  c++  java
  • CF375E Red and Black Tree

    cf

    这里的交换颜色其实就是选择相等数量的黑点和红点翻转颜色,并且可以发现交换后黑点总数(cnt)是不变的.所以可以从(cnt)不变入手,我们在树上选出(cnt)个黑点,其中如果有红点就翻转颜色(假设这里红点数量为(num)),如果有些黑点没被选中就任选其中(num)个翻转成红点,这与原问题是等价的.现在我们只要最小化(num)使得树满足条件.

    考虑dp,设(f_{x,j,k})表示在(x)子树内选中(j)个黑点,能够覆盖(x)条件的黑点为(k)子树内最小(num)((k)可以在子树外,这里规定(k)翻转产生的代价在(k)处算,即初始化时(f_{x,j,k}=[col_x=0&&x e k])).转移类似树形背包,每次合并两个状态(f_{x,j,k},f_{y,p,q})

    • (k=q),那么有(f_{x,j,k}+f_{y,p,k} o f'_{x,j+p,k})

    • (k e q),且(q)(y)子树内,那么有(f_{x,j,k}+min_{qin subtree(y)}f_{y,p,q} o f'_{x,j+p,k}).注意这时要保证(k otin subtree(y)),因为(k)的选择和翻转产生的代价是在(k)处算的,不这样规定就会少算代价

    • (k e q),且(q)(y)子树外,这时只要选择(k,q)其中的一个即可,即这种情况一定不优,所以不用考虑

    #include<bits/stdc++.h>
    #define LL long long
    #define db long double
    
    using namespace std;
    const int N=500+5,inf=1e9+7;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
        return x*w;
    }
    int to[N<<1],nt[N<<1],w[N<<1],hd[N],tot=1;
    void adde(int x,int y,int z)
    {
        ++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
        ++tot,to[tot]=x,nt[tot]=hd[y],w[tot]=z,hd[y]=tot;
    }
    short f[N][N][N],g[N][N],fa[N],dfn[N],ti,sz[N];
    int di[N][N],n,lm;
    bool co[N];
    void dd1(int x,int ffa,int xx,int nd)
    {
        di[x][xx]=nd;
        for(int i=hd[x];i;i=nt[i])
        {
        	int y=to[i];
        	if(y==ffa) continue;
        	dd1(y,x,xx,min((int)(nd+w[i]),inf));
        }
    }
    void dd2(int x)
    {
        dfn[x]=++ti;
        for(int i=hd[x];i;i=nt[i])
        {
        	int y=to[i];
        	if(y==fa[x]) continue;
        	fa[y]=x,dd2(y);
        }
    }
    void dfs(int x)
    {
        sz[x]=1;
        for(int z=1;z<=n;++z) if(z!=x&&di[z][x]<=lm) f[x][0][dfn[z]]=0;
        f[x][1][dfn[x]]=!co[x];
        for(int i=hd[x];i;i=nt[i])
        {
        	int y=to[i];
        	if(y==fa[x]) continue;
        	dfs(y);
        	for(int j=0;j<=sz[x]+sz[y];++j)
        	    memset(g[j],0x3f3f3f,sizeof(short)*(n+1));
        	for(int j=0;j<=sz[x];++j)
        	    for(int k=0;k<=sz[y];++k)
        	    {
            	short nv=1<<13;
            	for(int v=dfn[y];v<dfn[y]+sz[y];++v) nv=min(nv,f[y][k][v]);
            	for(int u=1;u<=n;++u)
          		{
           		    g[j+k][u]=min(g[j+k][u],(short)(f[x][j][u]+f[y][k][u]));
           		    if(u<dfn[y]||u>=dfn[y]+sz[y]) g[j+k][u]=min(g[j+k][u],(short)(f[x][j][u]+nv));
           		}
        	    }
        	for(int j=0;j<=sz[x]+sz[y];++j)
        	    memcpy(f[x][j],g[j],sizeof(short)*(n+1));
        	sz[x]+=sz[y];
        }
    }
    
    int main()
    {
        n=rd(),lm=rd();
        int cn=0;
        for(int i=1;i<=n;++i) cn+=co[i]=rd();
        for(int i=1;i<n;++i)
        {
        	int x=rd(),y=rd(),z=rd();
    	    adde(x,y,z);
        }
        for(int i=1;i<=n;++i) dd1(i,0,i,0);
        dd2(1);
        memset(f,0x3f3f3f,sizeof(f));
        dfs(1);
        short ans=1<<13;
        for(int i=1;i<=n;++i) ans=min(ans,f[1][cn][i]);
        cout<<(ans<=n?ans:-1);
        return 0;
    }
    
  • 相关阅读:
    入门金融学(1)
    递归之八皇后
    新手Oracle安装及使用入门
    RegExp正则校验之Java及R测试
    Mysql实现行列转换
    R语言之RCurl实现文件批量下载
    Consumer clientId=consumer-1, groupId=console-consumer-950] Connection to node -1 could not be
    线程池拒绝策略
    spring较为常用注解
    idea springboot启动报SLF4J:Failed to load class “org.slf4j.impl.StaticLoggerBinder”
  • 原文地址:https://www.cnblogs.com/smyjr/p/12655859.html
Copyright © 2011-2022 走看看