[关闭]
@Acqua 2019-01-25T01:49:58.000000Z 字数 1527 阅读 924

POJ3398 Perfect Service(Jan. 25th, 2019) 树形DP

动态规划 特殊技巧 独立解题

题目来源

题意

给定一棵有个结点的树,选取一个结点就能够支配与其直接相连的所有结点,求支配该树所有结点所需要选取的最小结点数。

思路

启发式思维,
使用图论模板,树形
表示结点被其父结点支配、被其自身支配、被其子结点支配。
如果结点被其父结点支配,就不可支配其子结点
结点只能由其自身或其子结点支配。

如果结点被自己支配,其子结点都被父结点支配,但因为服务器可以相连,所以也可以由自己支配。

如果结点被其子结点支配,则必定要有且仅有一个自身支配,其余的只能由其子结点支配。记录,用额外费用差值最小的代替

初始化:

反思

  1. 独立解题是一种高峰体验。

代码

  1. // La Pluie
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N=1e4+5;
  8. struct edge{
  9. int v,next;
  10. }e[N<<1];
  11. int head[N],k,dp[N][3],n;
  12. void adde(int u,int v){
  13. e[k]=(edge){v,head[u]};
  14. head[u]=k++;
  15. }
  16. void dfs(int u,int f){
  17. int mn=1e4+1;
  18. dp[u][1]=1;
  19. for(int i=head[u];i!=-1;i=e[i].next){
  20. int v=e[i].v;
  21. if(v==f) continue;
  22. dfs(v,u);
  23. dp[u][0]+=min(dp[v][1],dp[v][2]);
  24. dp[u][1]+=min(dp[v][0],dp[v][1]);
  25. dp[u][2]+=dp[v][2];
  26. mn=min(mn,dp[v][1]-dp[v][2]);
  27. }
  28. dp[u][2]+=mn;
  29. }
  30. int main(){
  31. while(~scanf("%d",&n)){
  32. memset(head,-1,sizeof(head));
  33. memset(dp,0,sizeof(dp));
  34. k=1;
  35. for(int i=1;i<n;i++){
  36. int u,v;
  37. scanf("%d%d",&u,&v);
  38. adde(u,v);adde(v,u);
  39. }
  40. int x;
  41. scanf("%d",&x);
  42. dfs(1,0);
  43. // for(int i=1;i<=n;i++) printf("%d %d %d\n",dp[i][0],dp[i][1],dp[i][2]);
  44. printf("%d\n",min(dp[1][1],dp[1][2]));
  45. if(x==-1) break;
  46. }
  47. return 0;
  48. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注