P1272 重建道路
阿新 • • 發佈:2020-10-23
https://www.luogu.com.cn/problem/P1272
一個神奇的樹形dp,大概就是下面這樣轉移的吧
dp[x][i]表示x為根,保留i個點最少刪除幾條邊
#include<iostream> #include<vector> #include<algorithm> #include<queue> using namespace std; const int maxn = 200+11; const int INF = 1e7; int dp[maxn][maxn]; vector<int>G[maxn]; void add(int x,int y){ G[x].push_back(y); } int siz[maxn]; int list[maxn]; int dfs(int x,int fa){ siz[x] =1; dp[x][1] = 0; for(int i=0;i<G[x].size();i++){ int p = G[x][i]; if(p == fa) continue; dfs(p,x); for(int i=1;i<=siz[x] + siz[p];i++) { list[i] = dp[x][i]; if(i > 1) dp[x][i] = INF; } for(int i=1;i<=siz[x];i++){ for(int j=1;j<=siz[p];j++){ dp[x][i+j] = min(list[i] + dp[p][j],min(dp[x][i+j],list[i+j] + 1)); // 不刪除當前邊 刪除當前邊 } } //不刪除當前邊算貢 siz[x] += siz[p]; dp[x][1]++; } return 0; } int main(){ // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); int n,p; cin >> n >> p; for(int i=1;i<=n+10;i++){ for(int j=2;j<=n+10;j++){ dp[i][j] = INF; } } for(int i=1;i<n;i++){ int x,y; cin>>x>>y; add(x,y); add(y,x); } dfs(1,-1); int ans = dp[1][p]; for(int i=2;i<=n;i++){ ans = min(ans,dp[i][p]+1); } cout<<ans<<endl; return 0; }