【HAOI 2015】樹上染色
阿新 • • 發佈:2020-11-25
\(\text{Description}\)
\(\text{Solution}\)
顯然設 \(f[i][j]\) 為根節點為 \(i\),\(j\) 個黑點的子樹最大收益。
??是否有哪裡不對
列一下轉移方程,畫一下圖就會發現有點問題:
\[f[u][j+k]=\max(f[u][j]+f[v][k]+\text w(u,v)\times (j\times k+(size_u-j)\times (size_v-k))) \]這樣轉移的話,我們只新增了 \((u,v)\) 邊對答案的貢獻,卻沒有運算元樹內部的邊因為兩棵子樹黑/白點相連而產生的貢獻。
我們提前算就行了,因為 \(m\)(即題目中的 \(k\)
所以轉移方程為:
\[f[u][j+k]=\max(f[u][j+k],f[u][j]+f[v][k]+\text w(u,v)\times ((m-k)\times k+(n-m-size_v+k)\times (size_v-k))) \]\(\text{Code}\)
#include <cstdio> #define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i) #define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i) #define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i]) #define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i]) #define print(x,y) write(x),putchar(y) template <class T> inline T read(const T sample) { T x=0; int f=1; char s; while((s=getchar())>'9'||s<'0') if(s=='-') f=-1; while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar(); return x*f; } template <class T> inline void write(const T x) { if(x<0) return (void) (putchar('-'),write(-x)); if(x>9) write(x/10); putchar(x%10^48); } template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;} template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;} template <class T> inline T fab(const T x) {return x>0?x:-x;} template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;} template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;} template <class T> inline T Swap(T &x,T &y) {x^=y^=x^=y;} #include <cstring> typedef long long ll; const int maxn=2005; ll f[maxn][maxn]; int n,m,head[maxn],nxt[maxn<<1],to[maxn<<1],cnt,siz[maxn],val[maxn<<1]; void addEdge(int u,int v,int w) { nxt[++cnt]=head[u],to[cnt]=v,head[u]=cnt,val[cnt]=w; } void DP(int u,int fa) { siz[u]=1; erep(i,u) { if(v==fa) continue; DP(v,u); fep(j,Min(m,siz[u]),0) fep(k,Min(siz[v],m),0) if(j+k<=m) f[u][j+k]=Max(f[u][j+k],f[u][j]+f[v][k]+1ll*val[i]*((m-k)*k+(n-m-siz[v]+k)*(siz[v]-k))); siz[u]+=siz[v]; } } int main() { int x,y,z; n=read(9),m=read(9); rep(i,1,n-1) { x=read(9),y=read(9),z=read(9); addEdge(x,y,z); addEdge(y,x,z); } DP(1,0); print(f[1][m],'\n'); return 0; }