[HAOI2015]樹上染色
阿新 • • 發佈:2018-10-19
space fine calc def 黑點 ret printf sum long long
題目描述(bzoj)
同上(洛谷)
思路
樹形DP
size[i]:i子樹的節點個數
f[i][j]:在i子樹中染j個黑點的最大貢獻
更新時考慮每條邊對答案的貢獻
即:這條邊兩側的黑點個數乘積*邊權+兩側白點個數乘積*邊權
然後是註意開long long,要不然一半分就沒了╮(╯_╰)╭
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define N 2005 int n,k; struct edge{ int u,v,nxt; long longdis; }e[N*2]; int cnt,first[N]; void add_edge(int x,int y,int z){ e[++cnt].u=x; e[cnt].v=y; e[cnt].dis=z; e[cnt].nxt=first[x]; first[x]=cnt; } bool vis[N]; int size[N]; long long f[N][N]; long long calc(long long dis,int siz,int y){ dis*=(y*(k-y)+(siz-y)*(n-k-siz+y)); returndis; } void dfs(int u){ vis[u]=true; size[u]=1; for(int i=first[u];i;i=e[i].nxt){ int v=e[i].v; if(!vis[v]){ dfs(v); for(int x=size[u];x>=0;x--){ for(int y=size[v];y>=0;y--){ long long sum=f[u][x]+f[v][y]+calc(e[i].dis,size[v],y); f[u][x+y]=max(f[u][x+y],sum); // printf("when size[%d]=%d,f[%d][%d]=%d\n",u,size[u],x,x+y,f[x][x+y]); } } size[u]+=size[v]; } } } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<n;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); add_edge(x,y,z); add_edge(y,x,z); } dfs(1); long long ans=f[1][k]; printf("%lld\n",ans); return 0; }
[HAOI2015]樹上染色