luogu P1272 重建道路

2022-06-20 20:12:11 字數 1132 閱讀 3842

很好的一道樹上dp

我會告訴你我想那個「-2」想了乙個下午嗎?

題面:一場可怕的**後,人們用n個牲口棚(1≤n≤150,編號1..n)重建了農夫john的牧場。由於人們沒有時間建設多餘的道路,所以現在從乙個牲口棚到另乙個牲口棚的道路是惟一的。因此,牧場運輸系統可以被構建成一棵樹。john想要知道另一次**會造成多嚴重的破壞。有些道路一旦被毀壞,就會使一棵含有p(1≤p≤n)個牲口棚的子樹和剩餘的牲口棚分離,john想知道這些道路的最小數目。

輸入:第1行:2個整數,n和p

第2..n行:每行2個整數i和j,表示節點i是節點j的父節點。

輸出:單獨一行,包含一旦被破壞將分離出恰含p個節點的子樹的道路的最小數目。

分析:\(dp[i][j]\)表示計算至\(i\)時,分離出整顆大小為\(j\)的子樹(包括\(i\))所需切掉的最少道路數。

初始化乙個點的時候,把它的所有連邊給去掉,\(dp[i][1]=du[i]\)。

父節點每與乙個子節點合併,需要將dp之和-2,為什麼?

因為在初始化時,已經將u的\(u->v\)去掉,也已經將\(v\)的\(v->u\)去掉,而如果想將含\(u\)連通塊與含\(v\)連通塊相連,這條邊不能被去掉。

然後我一直在想為什麼每一次都要減去2

答案是:我們的dp操作規則是預設一開始所有的點都被切開,所以我們的運算要遵循這個規則,每一次計算也就是一次合併,無論哪兩個dp值都遵循著不與外界聯絡的規律,所以兩個dp值相加一定要-2.

code:

#include#include#includeusing namespace std;

const int inf=0x3f3f3f3f;

const int n=201;

struct edgee[n*2];

int du[n],a[n],dp[n][n];

int n,k,res=inf,edgecnt=0;

void addedge(int u,int v)

void dfs(int u,int fa)

}res=min(res,dp[u][k]);

}int main()

dfs(1,0);

printf("%d",res);

return 0;

}

luogu P1272 重建道路

一場可怕的 後,人們用n個牲口棚 1 n 150,編號1.n 重建了農夫john的牧場。由於人們沒有時間建設多餘的道路,所以現在從乙個牲口棚到另乙個牲口棚的道路是惟一的。因此,牧場運輸系統可以被構建成一棵樹。john想要知道另一次 會造成多嚴重的破壞。有些道路一旦被毀壞,就會使一棵含有p 1 p n...

luogu P1272 重建道路 樹形DP

luogu p1272 重建道路 x n y n z n 題目描述 一場可怕的 後,人們用n個牲口棚 1 n 150,編號1.n 重建了農夫john的牧場。由於人們沒有時間建設多餘的道路,所以現在從乙個牲口棚到另乙個牲口棚的道路是惟一的。因此,牧場運輸系統可以被構建成一棵樹。john想要知道另一次 ...

P1272 重建道路

p1272 重建道路 題意 有一棵n個點的樹,求刪掉最少的邊數,使得其中p個點的子樹和另一部分分離 dp i j 表示編號為i的點周圍組成j個點的樹最少要刪的邊數 初始狀態 dp i 1 連線這個點的邊數 每個點都是點數為1的樹 然後去考慮連線兩個點,使子樹的點數增多。有兩個點數都是1的樹dp i ...