[bzoj4033][HAOI2015]树上染色

题面太狗,这是链接

先发个暴力刷访问量。

// It is made by XZZ
#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
typedef long long ll;
il int gi(){
    rg int x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int f[2001][2001];
int main(){
    int n=gi(),m=gi(),a,b,c,ans=0;
    rep(i,1,n)rep(j,i+1,n)f[i][j]=f[j][i]=1000000000;
    rep(i,2,n)a=gi(),b=gi(),c=gi(),f[a][b]=f[b][a]=c;
    rep(k,1,n)rep(i,1,n)rep(j,1,n)f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
    rep(i,0,(1<<n)-1){
	int cnt=0,o=i,res=0;
	while(o)cnt++,o-=o&-o;
	if(cnt!=m)continue;
	rep(j,1,n)rep(k,j+1,n){
	    bool aaa=i&(1<<(j-1)),bbb=i&(1<<(k-1));
	    if(aaa==bbb)res+=f[j][k];
	}
	ans=max(ans,res);
    }printf("%d\n",ans);
    return 0;
}

考的时候我想这就是个裸的树形DP,然后设f[i][j]为i为根染黑j的点的答案,然后没打出来。。。

打了上面代码然后太匆忙了CE(\(我打的froepen!——QYP\)

然后就GG了。。。130->100

正解的话。。。考虑点太麻烦了,就考虑一下边

每条边\((a,b)\)答案的贡献\(ff[i]=w[i]×(a.Black×b.Black+a.white×b.White)\)

即:(上面黑点×下面黑点+上面白点×下面白点)×权值。

所以,就可以转移了。

枚举儿子,再枚举子树里多少黑点,再枚举这个儿子中放的黑点,答案就出来了

设当前节点是\(now\),儿子为\(t\),这里\(size[now]\)个节点,j个黑点,子树内\(size[t]\)个节点,\(kk\)个黑点(不能与\(k\)混淆),则这条边贡献是:

\(w[i](kk(k-kk)+(siz[t]-kk)(n-k-siz[t]+kk))\)

还要加上其他边的贡献。

自己想一下,应该很清楚。

// It is made by XZZ
#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
#define t (dis[i])
typedef long long ll;
il ll gi(){
    rg ll x=0,f=1;rg char ch=getchar();
    while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
const int maxn=2011,maxm=maxn<<1;
int id=0,fir[maxn],nxt[maxm],dis[maxm],n;ll w[maxm],k;
il vd add(int a,int b,ll c){nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;}
ll siz[maxn],f[maxn][maxn];
il vd dfs(int now,int fa=-1){
    f[now][0]=f[now][1]=0,siz[now]=1;
    erep(i,now)if(t^fa){
	dfs(t,now);
	siz[now]+=siz[t];
	drep(j,siz[now],0)rep(kk,0,siz[t])if(kk<=j){
	    ll delta=kk*(k-kk)+(siz[t]-kk)*(n-k-siz[t]+kk);
	    delta=delta*w[i]+f[t][kk];
	    f[now][j]=max(f[now][j],f[now][j-kk]+delta);
	}
    }
}
int main(){
    n=gi();
    ll a,b,c;
    k=gi();
    rep(i,2,n)a=gi(),b=gi(),c=gi(),add(a,b,c),add(b,a,c);
    rep(i,1,n)rep(j,1,k)f[i][j]=-1000000000000000ll;
    dfs(1,0);printf("%lld\n",f[1][k]);
    return 0;
}
posted @ 2017-08-09 16:36  菜狗xzz  阅读(212)  评论(0编辑  收藏  举报