[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;
}
博主是蒟蒻,有问题请指出,谢谢!
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。
本博客中博文均为原创,未经博主允许请勿随意转载,谢谢。