BZOJ 3257 樹的難題

2021-07-10 12:31:38 字數 1824 閱讀 7356

3257: 樹的難題

time limit: 10 sec  memory limit: 128 mb

submit: 56  solved: 39

[submit][status][discuss]

description

給出乙個無根樹。樹有n個點,邊有權值。每個點都有顏色,是黑色、白色、

灰色這三種顏色之一,稱為一棵三色樹。

可愛的 alice覺得,乙個三色樹為均衡的,當且僅當,樹中不含有黑色結點

或者含有至多乙個白色節點。然而,給出的三色樹可能並不滿足這個性質。  

所以,alice打算刪去若干條邊使得形成的森林中每棵樹都是均衡的,花費 

的代價等於刪去的邊的權值之和。請你計算需要花費的代價最小是多少。  

注意,輸入檔案包含多組測試資料。

input

第一行包含乙個正整數 t,表示有 t組測試資料。接下來依次是 t組測試數

據。每組測試資料的第一行包含乙個正整數 n。

第二行包含 n個 0、1、2之一的整數,依次表示點 1到點 n的顏色。其中,

0 表示黑色,1表示白色,2表示灰色。

接下來 n-1行,每行為三個整數ui、vi、c i,表示一條權值等於ci的邊(ui, vi)。

樹形dp

當至多取乙個的時候,我們需要計算出來不取的答案,然後減掉取min,即至多取乙個。

#include 

#include

#include

#include

#define maxn 500010

using namespace std;

typedef long long ll;

ll dp[maxn][3];

int n;

struct edgeedge[maxn * 2];

int h[maxn], cnt;

void add(int u, int v, int d)

const ll inf = 1ll << 50;

int fa[maxn], c[maxn];

ll d[maxn];

int min(int a, int b, int c)

/* dp[u][2]//乙個白點。

dp[u][1]//無白點

dp[u][0]//無黑點

*/void dfs(int u)

if(c[u] == 0)

q = ret;

for(int i = h[u]; i; i = edge[i].next)

dp[u][2] = q;

dp[u][1] = ret;

dp[u][0] = inf; }

if(c[u] == 1)

dp[u][2] = ret2;

dp[u][1] = inf;

dp[u][0] = ret1; }

if(c[u] == 2)

q = ret;

for(int i = h[u]; i; i = edge[i].next)

dp[u][2] = q;

dp[u][1] = ret;

dp[u][0] = ret1; }}

int main()

d[1] = 0;dfs(1);

ll ans = min(dp[1][0], dp[1][1]);

ans = min(ans, dp[1][2]);

printf("%lld\n", ans);

} return 0;

}

bzoj3257 樹的難題

description 給出乙個無根樹。樹有n個點,邊有權值。每個點都有顏色,是黑色 白色 灰色這三種顏色之一,稱為一棵三色樹。可愛的 alice覺得,乙個三色樹為均衡的,當且僅當,樹中不含有黑色結點 或者含有至多乙個白色節點。然而,給出的三色樹可能並不滿足這個性質。所以,alice打算刪去若干條邊...

BZOJ3257 樹的難題

設 f x i j 表示以 x 為根的子樹,與 x 連通部分有 i 個黑點,j 個白點,不聯通部分都是均衡的最小代價。若 i 1 則視作 1 若 j 2 則視作 2 然後進行樹形dp即可,轉移的時候如果不要那棵子樹,那麼那棵子樹的狀態必須滿足 i j 2 時間複雜度 o n include defi...

1900 985的「樹」難題

time limit 1 sec memory limit 128 mb 985給你一棵 樹 以及它的根節點,要求你先判定它是否是一棵樹,其次他想知道每個節點的 太子 數目以及它的父親 root的話輸出自己 太子判定條件 一 若x是y的孩子節點,那麼x是y的 太子 二 若x是y的 太子 且y是z的 ...