其他分享
首页 > 其他分享> > CF375E Red and Black Tree

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