ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF375E Red and Black Tree

2020-04-07 20:52:59  阅读:314  来源: 互联网

标签:ch 子树内 黑点 Tree int num Black CF375E 翻转


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\ne k]\)).转移类似树形背包,每次合并两个状态\(f_{x,j,k},f_{y,p,q}\)时

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

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

  • 若\(k\ne 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;
}

标签:ch,子树内,黑点,Tree,int,num,Black,CF375E,翻转
来源: https://www.cnblogs.com/smyjr/p/12655859.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有