重建道路 洛谷p1272

2021-08-30 08:38:52 字數 1503 閱讀 6567

一場可怕的**後,人們用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個節點的子樹的道路的最小數目。

輸入樣例#1:複製

11 6

1 21 3

1 41 5

2 62 7

2 84 9

4 10

4 11

輸出樣例#1:複製

2
【樣例解釋】

如果道路1-4和1-5被破壞,含有節點(1,2,3,6,7,8)的子樹將被分離出來

我們設dp[k][i][j]表示以i為根的子樹,在前k個兒子中,分離出乙個大小為j的子樹(必須包含i),所需要最少的操作次數。

那麼我們每計算到第k+1個新的兒子v時(full_son[v]表示v的兒子個數),

dp[k+1][i][j]=min(dp[k][i][j-t]+dp[full_son[v]][v][t]);

由於乙個樹形關係,我們需要在乙個dfs上進行dp,即先dfs(v),然後更新dp[k+1][i][j]。

這個k的一維顯然可以用滾動陣列優化掉。

那麼就是

j=m->1 t=1->j dp[i][j]=min(dp[i][j-t]+dp[v][t]);

同時,dp一律要注意初始化,即剛開始時所有的dp[i][1]=du[i](du[i]表示與i連邊的節點數,又稱i的入度(樹是無向邊喲!))

#include#define f(i,l,r) for(i=(l);i<=(r);i++)

#define ff(i,r,l) for(i=(r);i>=(l);i--)

using namespace std;

const int maxn=155,inf=10000000;

int n,p;

struct edgee[maxn<<1];

int h[maxn],tot;

int deg[maxn];

int dp[maxn][maxn],ans=inf;

inline void add(int u,int v)

inline void dfs(int u,int fa)

} }ans=min(ans,dp[u][p]);

}int main()

dfs(1,0);

cout

}

洛谷P1272 道路重建

題目大意 給定乙個 n 個節點的樹,求至少剪掉多少條邊才能使得從樹中分離出乙個大小為 m 的子樹。題解 考慮樹形 dp,定義 dp u i t 為以 u 為根節點與前 i 個子節點構成的子樹中,保留 t 個節點 包括根節點 的最小代價,則狀態轉移方程為 dp u i t min dp u i t d...

洛谷 P1272 重建道路

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

洛谷 P1272 重建道路

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