BZOJ4033&&洛谷P3177 [HAOI2015]树上染色

树形背包dp

dp我会讲嘛?还是这么难的。。

大概思路就是一条边的贡献是它连接的两个块中的颜色个数bulabula的算了,盗个题解吧(背景是我的233)


原文

代码(我的是STL版的)

//By AcerMo
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int 
using namespace std;
const int M=3050;
struct edge
{
    int to,cost;
}now;
int n,k,siz[M];
lli dis[M][M];
vector<edge>g[M];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch>'9'||ch<'0') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
void dfs(int x, int fa) 
{
    siz[x]=1;dis[x][0]=dis[x][1]=0;
    for (int i=0;i<g[x].size();i++)
    {
        int go=g[x][i].to;
        if (go==fa) continue;
        dfs(go,x);siz[x]+=siz[go];
    }
    for (int i=0;i<g[x].size();i++)
    {
        int v=g[x][i].to,w=g[x][i].cost;
        if (v==fa) continue;
        for (int p=min(siz[x],k);p>=0;p--) 
        for (int q=0;q<=min(p,siz[v]);q++) 
		if (dis[x][p-q]>=0) 
		{
        	lli val= 1ll*(q*(k-q)+(siz[v]-q)*(n-k+q-siz[v]))*w; 
            dis[x][p]=max(dis[x][p],dis[x][p-q]+dis[v][q]+val);
        }
    }
    return ;
}
int main() 
{
    n=read();k=read();   
    for (int i=1;i<n;i++) 
	{
        int a=read(),b=read(),c=read();
        now.to=b;now.cost=c;g[a].push_back(now);
        now.to=a;now.cost=c;g[b].push_back(now);
    }
    memset(dis,-1,sizeof(dis));
    dfs(1,0);
    printf("%lld\n",dis[1][k]);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/81054906