COJ1115(Special Operation)
题目大意:给定一棵树,求最大点独立集中点的数目。
这题昨晚一开始想到可以转化为求二部图的最大匹配来做,没估计复杂度,最后超时了。
后来就考虑把树分成两部分,取结点较多的那部分作为结果,提交后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 }
分类:
ACM题解
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· ShadowSql之.net sql拼写神器
· 感觉程序员要被 AI 淘汰了?学什么才有机会?
· MQTT协议发布和订阅的实现,一步步带你实现发布订阅服务。
· Dify开发必备:分享8个官方文档不曾解释的关键技巧