BZOJ 1907 樹的路徑覆蓋【樹形DP】
阿新 • • 發佈:2018-11-08
好像可以貪心?
表示選擇了/沒有選擇 與父親間的邊時,以 為根的子樹的最小路徑覆蓋數
就是平常轉移,算一下拐角:
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define rep(i,x,y) for(int i=(x);i<=(y);i++) #define red(i,x,y) for(int i=(x);i>=(y);i--) using namespace std; const int N=2e4+5; int t,n,f[N][2]; int cnt,to[N<<1],nxt[N<<1],head[N]; inline int read() { int x=0;char ch=getchar();bool f=0; while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?-x:x; } void ins(int x,int y) { to[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt; } void dfs(int x,int fa) { int ret=0; f[x][0]=f[x][1]=1; for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(y!=fa) { dfs(y,x); f[x][0]=min(f[x][0]+f[y][0],f[x][1]+f[y][1]-1); f[x][1]=min(f[x][1]+f[y][0],ret+f[y][1]);ret+=f[y][0]; } } } int main() { t=read(); while(t--) { cnt=0; memset(f,0,sizeof(f)); memset(head,0,sizeof(head)); n=read(); rep(i,2,n) { int x=read(),y=read(); ins(x,y),ins(y,x); } dfs(1,0); printf("%d\n",min(f[1][0],f[1][1])); } return 0; }