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

    Link
    单纯形是不可能的,这辈子都不可能单纯形的。
    考虑树形dp,设(f_{u,k,p})为在(u)子树内选(k)个黑点,(u)选的黑点是(p)的最小代价。
    转移和树形背包差不多,不妨设(vin son_u),考虑合并(f_{u,i,p},f_{v,j,q})
    (p=q),则(f_{u,i,p}+f_{v,j,p} ightarrow f_{u,i+j,p})
    (q)(v)子树内,则此时(p)一定不在(v)子树内,(f_{u,i,p}+f_{v,j,q} ightarrow f_{u,i+j,p})
    (q)(v)子树外,不难发现此时若(p e q)则一定不优,因此不予考虑。

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<utility>
    using i16=short;
    using i64=long long;
    using pi=std::pair<int,int>;
    const int N=507;const i16 inf=16383;
    int n,x,dfn[N],size[N],col[N],ban[N][N];i16 f[N][N][N],t[N][N];std::vector<pi>e[N];
    int read(){int x;scanf("%d",&x);return x;}
    void dfs1(int u,int f,int r,i64 d)
    {
        ban[u][r]=d>x;
        for(auto[v,w]:e[u]) if(v^f) dfs1(v,u,r,d+w);
    }
    void dfs2(int u,int f)
    {
        static int t=0;dfn[u]=++t;
        for(auto[v,w]:e[u]) if(v^f) dfs2(v,u);
    }
    void dp(int u,int fa)
    {
        size[u]=1;f[u][col[u]][dfn[u]]=inf,f[u][!col[u]][dfn[u]]=1;
        for(int i=1;i<=n;++i) if(i^u) if(f[u][1][dfn[i]]=inf,ban[u][i]) f[u][0][dfn[i]]=inf;
        for(auto[v,w]:e[u])
        {
    	if(v==fa) continue;
    	dp(v,u),memset(t,0x3f,sizeof t);
    	for(int j=0;j<=size[v];++j)
    	{
    	    i16 mn=inf;
    	    for(int k=dfn[v];k<dfn[v]+size[v];++k) mn=std::min(mn,f[v][j][k]);
    	    for(int i=0;i<=size[u];++i)
    		for(int k=1;k<=n;++k)
    		{
    		    t[i+j][k]=std::min(t[i+j][k],(i16)(f[u][i][k]+f[v][j][k]));
    		    if(k<dfn[v]||k>=dfn[v]+size[v]) t[i+j][k]=std::min(t[i+j][k],(i16)(f[u][i][k]+mn));
    		}
    	}
    	size[u]+=size[v],memcpy(f[u],t,sizeof t);
        }
    }
    
    int main()
    {
        n=read(),x=read();i16 num=0;
        for(int i=1;i<=n;++i) num+=col[i]=read();
        for(int i=1,u,v,w;i<n;++i) u=read(),v=read(),w=read(),e[u].push_back({v,w}),e[v].push_back({u,w});
        for(int i=1;i<=n;++i) dfs1(i,0,i,0);
        dfs2(1,0),dp(1,0);
        for(int i=0;i<=n;++i) for(int j=1;j<=n;++j) if(num>=f[1][i][j]) return !printf("%d",i);
        return puts("-1"),0;
    }
    
  • 相关阅读:
    元素的ID和Name有什么区别???[转自"天道酬勤"]
    招聘时会问到的问题
    关于asp.net开发B/S应用系统的思索和讨论
    软件文档知多少?
    C# 编码规范和编程好习惯
    [转]多层结构来开发ASP.NET程序
    ASP.NET页面间的传值的几种方法
    为sql server 表数据生成创建的储存过程(生成insert 脚本)
    XHTML+CSS应用教程——利用CSS实现双语导航条
    XHTML+CSS应用教程——CSS实现文字的双影
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12652244.html
Copyright © 2011-2022 走看看