题目大意:给定一棵树,求最大点独立集中点的数目。
这题昨晚一开始想到可以转化为求二部图的最大匹配来做,没估计复杂度,最后超时了。
后来就考虑把树分成两部分,取结点较多的那部分作为结果,提交后WA。
再后来,我考虑给树定一个根结点,然后分层,统计每层的结点数目,然后再转化为DP问题去做,相当于是分层DP,结果还是WA。
昨天晚上躺在床上时,突然想到曾经听说过树形DP,难道这题正是?今天翻了下刘汝佳的白书,学习了下树形DP,然后果断AC。

1 #include <stdio.h> 2 #include <vector> 3 #define MAX(a,b) ((a)>(b)?(a):(b)) 4 #define N 50000 5 6 using namespace std; 7 8 vector<int> g[N]; 9 10 int p[N],d[N],c[N],sums[N],sumgs[N],dmax,n; 11 12 void read_tree() 13 { 14 int i,u,v; 15 for(i=1;i<n;i++) 16 { 17 scanf("%d%d",&u,&v),u--,v--; 18 g[u].push_back(v); 19 g[v].push_back(u); 20 } 21 } 22 void dfs(int u,int fa) 23 { 24 int i,v; 25 d[u]=(fa==-1?0:d[fa]+1); 26 dmax=MAX(dmax,d[u]); 27 for(i=0;i<g[u].size();i++) 28 { 29 v=g[u][i]; 30 if(v!=fa) dfs(v,p[v]=u); 31 } 32 } 33 void dp() 34 { 35 int i,j; 36 for(i=dmax;i>=0;i--) 37 { 38 for(j=0;j<n;j++) 39 { 40 if(d[j]!=i) continue; 41 c[j]=MAX(sums[j],sumgs[j]+1); 42 if(i>0) sums[p[j]]+=c[j]; 43 if(i>1) sumgs[p[p[j]]]+=c[j]; 44 } 45 } 46 } 47 int main() 48 { 49 int i; 50 while(~scanf("%d",&n)) 51 { 52 for(i=0;i<n;i++) g[i].clear(); 53 memset(sums,0,sizeof(sums)); 54 memset(sumgs,0,sizeof(sumgs)); 55 dmax=0; 56 read_tree(); 57 dfs(0,-1); 58 dp(); 59 printf("%d\n",c[0]); 60 } 61 return 0; 62 }

1 #include <stdio.h> 2 #include <memory.h> 3 #define N 50001 4 int x[N],y[N],u[N],v[N],next[N],first[N],n; 5 char vis[N]; 6 int con(int i,int j) 7 { 8 int e; 9 for(e=first[i];e;e=next[e]) if(v[e]==j) return 1; 10 return 0; 11 } 12 int path(int i) 13 { 14 int j; 15 for(j=1;j<=n;j++)if((con(i,j)||con(j,i))&&!vis[j]) 16 { 17 vis[j]=1; 18 if(y[j]==-1 || path(y[j])) 19 { 20 x[i]=j; 21 y[j]=i; 22 return 1; 23 } 24 } 25 return 0; 26 } 27 int maxmatch() 28 { 29 int i,cnt=0; 30 for(i=1;i<=n;i++)if(x[i]==-1) 31 { 32 memset(vis,0,sizeof(vis)); 33 cnt+=path(i); 34 } 35 return cnt; 36 } 37 int main() 38 { 39 int i,j,e; 40 freopen("in.txt","r",stdin); 41 freopen("out.txt","w",stdout); 42 while(~scanf("%d",&n)) 43 { 44 memset(first,0,sizeof(first)); 45 for(e=1;e<n;e++) 46 { 47 scanf("%d%d",&u[e],&v[e]); 48 next[e]=first[u[e]]; 49 first[u[e]]=e; 50 } 51 printf("%d\n",n-maxmatch()/2); 52 } 53 return 0; 54 }