1. 程式人生 > >Luogu P1272 重建道路 DP

Luogu P1272 重建道路 DP

。。 font algo efi pri == bsp ostream time

剛才瞅了半天自己當初寫的,終於瞅出來了。。。QWQ


設f[i][j]表示以i為根的子樹,包含j個節點所需砍掉的最小邊數

那麽可知f[u][1]=u的度;

方程:f[u][j]=min(f[u][j],f[u][j-k]+f[v][k]-2);

為何減2? 因為你已經默認了把與自己相連的所有邊都去掉了,於是相當於多去了邊(u,v)兩次,所以要-2

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define R register int
using
namespace std; const int Inf=0x3f3f3f3f,N=201; struct edge{ int v,nxt; }e[N<<1]; int n,m,ans=Inf,cnt; int r[N],fir[N],f[N][N]; inline int g() { R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==-?-1:fix; do ret=(ret<<3)+(ret<<1)+(ch^48); while
(isdigit(ch=getchar())); return ret*fix; } inline void add(int u,int v) {e[++cnt].v=v,e[cnt].nxt=fir[u],fir[u]=cnt;} void dfs(int u,int fa) { f[u][1]=r[u]; for(R i=fir[u],v=e[i].v;i;i=e[i].nxt,v=e[i].v) { if(v!=fa) { dfs(v,u); for(R j=m;j>=1;j--)
for(R k=1;k<=j;k++) f[u][j]=min(f[u][j],f[u][j-k]+f[v][k]-2); } } ans=min(f[u][m],ans); } signed main() { n=g(),m=g();memset(f,0x3f,sizeof(f)); for(R i=1;i<n;i++) {R u=g(),v=g(); add(u,v),add(v,u); r[u]++,r[v]++;} dfs(1,0); printf("%d\n",ans); }

2019.04.28

Luogu P1272 重建道路 DP