有一棵點數為 \(n\) 的樹,樹邊有邊權。給你乙個在 \(0~ n\) 之內的正整數 \(k\) ,你要在這棵樹中選擇 \(k\)個點,將其染成黑色,並將其他 的\(n-k\)個點染成白色 。 將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間的距離的和的受益。問受益最大值是多少。
有點難想的dp 我果然太菜了
%%%__stdcall
\(f[i][j]\) 為以\(i\)為根的子樹, 選了染了\(j\)個黑點的最大貢獻
然後就是樹形揹包。。
siz[u]為以u為根的子樹大小
for (int j = min(k, siz[u]); j >= 0; j--)
for (int k = 0; k <= min(j, siz[v]); k++)
if (f[u][j-k] >= 0)
貢獻為子樹貢獻加上該邊的貢獻(子樹黑點個數 * 其它黑點個數 * 邊權 + 子樹白點個數 * 其它白點個數 * 邊權 )
#include#define ll long long
#define rg register
using namespace std;
inline int gi()
const int n = 2010;
struct node g[n<<1];
int last[n], gl;
inline void add(int z, int x, int y) ;
last[x] = gl;
g[++gl] = (node) ;
last[y] = gl;
return ;
}int siz[n], n, k;
long long f[n][n];
inline void init(int u, int fa)
return ;
}#define min(x, y) ((xy)?x:y)
inline void dfs(int u, int fa)
}return ;
}int main()
洛谷 P3177 HAOI2015 樹上染色
懶得複製題面了直接傳送門吧 直接求點與點之間的距離感覺不是很好求,所以我們考慮換乙個求法。瞄了一眼題解 距離跟路徑上邊的長度有關,所以我們直接來看每一條邊的貢獻吧 這誰想得到啊 對於每一條邊,它的貢獻等於 一邊的白點數 另一邊的白點數 一邊的黑點數 另一邊的黑點數 邊權 然後。我又卡住了。再次瞄題解...
HAOI2015 樹上染色 洛谷 3177
然後無根樹轉有根樹。設f x j 表示以x為根的子樹,選取了j個黑點,連線x和father x 的這條邊最大的貢獻。然後揹包一下就好了。詳細一點,對於這條邊。子樹下有 j 個黑點,那麼在其他位置就有k j個黑點,所以由於黑點這條邊被走過j k j 次。子樹下有si ze x j 個白點,其他位置有n...
洛谷P3177 樹上染色
題目 一道非常好的樹形dp。狀態 dp u n 為u的子樹選n個黑點所能得到的收益最大值。則最終的結果就是 dp root k root 可以為任何值,為了方便,使 root 1 然後考慮怎麼狀態轉移,狀態轉移一般要從方程和邊界入手,考慮用揹包的思想,得到方程 dp now j max dp now...