zoukankan      html  css  js  c++  java
  • bzoj4033 [HAOI2015]树上染色

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4033

    重要的思路:与其考虑每一个点对的贡献,不如考虑每条边的贡献(==被经过了几次)!

    树形dp。

    总共的黑点和白点的个数都是已知的,所以知道子树里有多少个黑点,就能算出子树的根到它的父亲的那条边被经过多少次。

      (因为子树中黑点数是包含根的,所以求子树向外的那条边比较方便)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int N=2005;
    int n,k,head[N],xnt,rt,siz[N];
    ll dp[N][N],ed[N];
    struct Edge{
        int next,to;
        ll w;
        Edge(int n=0,int t=0,ll c=0):next(n),to(t),w(c) {}
    }edge[N<<1];
    void add(int a,int b,ll c)
    {
        edge[++xnt]=Edge(head[a],b,c);head[a]=xnt;
        edge[++xnt]=Edge(head[b],a,c);head[b]=xnt;
    }
    void dfs(int cr,int fa)
    {
        siz[cr]=1;
        for(int i=head[cr],v;i;i=edge[i].next)
        {
            if((v=edge[i].to)==fa)continue;
            ed[v]=edge[i].w;
            dfs(v,cr);
            for(int j=min(k,siz[cr]+siz[v]);j>=0;j--)
                for(int l=max(0,j-siz[cr]);l<=j&&l<=siz[v];l++)
                    dp[cr][j]=max(dp[cr][j],dp[cr][j-l]+dp[v][l]);
            siz[cr]+=siz[v];
        }
        if(!fa)return;
        for(int j=0;j<=k&&j<=siz[cr];j++)dp[cr][j]+=(j*(k-j)+(siz[cr]-j)*(n-k-(siz[cr]-j)))*ed[cr];
    }
    int main()
    {
        scanf("%d%d",&n,&k);int x,y;ll z;
        for(int i=1;i<n;i++)
            scanf("%d%d%lld",&x,&y,&z),add(x,y,z);
        dfs(1,0);
        printf("%lld",dp[1][k]);
        return 0;
    }
  • 相关阅读:
    针对web高并发量的处理
    外边距合并,外边距折叠
    cookie 和session 的区别:
    ng-if ng-show ng-hide 的区别
    JavaScript中的arguments,callee,caller
    git常见命令
    jQuery中.bind() .live() .delegate() .on()的区别
    为什么要使用sass
    js兼容性记录
    poj1004
  • 原文地址:https://www.cnblogs.com/Narh/p/9163724.html
Copyright © 2011-2022 走看看