题目链接

id=36043">UVA - 1218 Perfect Service

题意

有n台电脑。互相以无根树的方式连接,现要将当中一部分电脑作为server,且要求每台电脑必须连接且仅仅能连接一台server(不包含作为server的电脑)。求最少须要多少台电脑作为server。

思路

典型的树形dp问题,那么我们来建立模型。

d(u,0):u是server,孩子是不是server均可

d(u,1):u不是server,u的父亲是server,u的孩子不能是server

d(u,2):u不是server且u的父亲不是server,u的孩子必须有且仅有一个是server。

那么显然的

d(u,0) = 1 + Sum( Min(d(v,1), d(v,0)) ) |v是u的孩子

d(u,1) = Sum(d(v,2))

d(u,2)稍复杂些。由于仅仅能有一个孩子是server,所以须要遍历每一个孩子为server的情况,每一轮遍历都要同一时候计算其它全部孩子,须要O(N^2)的时间。

显然这样会有非常多反复计算的情况,当然能够记忆化来加高速度,可是另一个更快的小技巧。由于d(u,1)和d(u,2)的唯一差别就是d(u,2)的孩子有一个server

那么我们能够得出

d(u,2) = Min(d(u,1)-d(v,2)+d(v,0)) |v是u的孩子

仍是遍历设每一个孩子为server。每一轮的操作为O(1),整体为O(N)

代码

ps:由于d(u,2)初始要设为无穷大,就设了0x3f3f3f3f,结果改成N就好了,找了好久才找出问题出在这,由于这个wrong了好多遍,但还是不知道为什么会wrong,知道原因的道友请不吝指点。

第一遍a的代码

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <cstdlib>
  6. #include <vector>
  7. #include <cmath>
  8. #include <map>
  9. using namespace std;
  10. const int N = 10009;
  11. vector<int> g[N];
  12. int dp[N][3];
  13. void dfs(int u, int fa)
  14. {
  15. for(int i=0; i<g[u].size(); i++)
  16. {
  17. if(g[u][i] != fa)
  18. dfs(g[u][i], u);
  19. }
  20. dp[u][0] = 1;
  21. dp[u][1] = 0;
  22. dp[u][2] = N;
  23. for(int i=0; i<g[u].size(); i++)
  24. {
  25. if(g[u][i] != fa)
  26. {
  27. dp[u][0] += min(dp[g[u][i]][0], dp[g[u][i]][1]);
  28. dp[u][1] += dp[g[u][i]][2];
  29. }
  30. }
  31. bool f = true;
  32. for(int i=0; i<g[u].size(); i++)
  33. {
  34. if(g[u][i] != fa)
  35. {
  36. f = false;
  37. dp[u][2] = min(dp[u][2], dp[u][1]+dp[g[u][i]][0]-dp[g[u][i]][2]);
  38. }
  39. }
  40. }
  41. int main()
  42. {
  43. int n;
  44. while(cin>>n)
  45. {
  46. memset(dp, -1, sizeof(dp));
  47. int a, b;
  48. for(int i=1; i<n; i++)
  49. {
  50. cin>>a>>b;
  51. g[a].push_back(b);
  52. g[b].push_back(a);
  53. }
  54. dfs(1, -1);
  55. cout<<min(dp[1][0], dp[1][2])<<endl;
  56. cin>>a;
  57. if(a == -1)
  58. break;
  59. for(int i=1; i<=n; i++)
  60. g[i].clear();
  61. }
  62. return 0;
  63. }

观摩大神代码后进行改动的精简版

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <cstdlib>
  6. #include <vector>
  7. #include <cmath>
  8. #include <map>
  9. using namespace std;
  10. const int N = 10009;
  11. vector<int> g[N];
  12. int dp[N][3];
  13. void dfs(int u, int fa)
  14. {
  15. dp[u][0] = 1;
  16. dp[u][1] = 0;
  17. dp[u][2] = N;
  18. for(int i=0; i<g[u].size(); i++)
  19. {
  20. if(g[u][i] != fa)
  21. {
  22. dfs(g[u][i], u);
  23. dp[u][0] += min(dp[g[u][i]][0], dp[g[u][i]][1]);
  24. dp[u][1] += dp[g[u][i]][2];
  25. }
  26. }
  27. for(int i=0; i<g[u].size(); i++)
  28. {
  29. if(g[u][i] != fa)
  30. dp[u][2] = min(dp[u][2], dp[u][1]+dp[g[u][i]][0]-dp[g[u][i]][2]);
  31. }
  32. }
  33. int main()
  34. {
  35. int n;
  36. while(cin>>n)
  37. {
  38. int a, b;
  39. for(int i=1; i<n; i++)
  40. {
  41. cin>>a>>b;
  42. g[a].push_back(b);
  43. g[b].push_back(a);
  44. }
  45. dfs(1, -1);
  46. cout<<min(dp[1][0], dp[1][2])<<endl;
  47. cin>>a;
  48. if(a == -1)
  49. break;
  50. for(int i=1; i<=n; i++)
  51. g[i].clear();
  52. }
  53. return 0;
  54. }

UVA - 1218 Perfect Service(树形dp)的更多相关文章

  1. UVA - 1218 Perfect Service (树形dp)(inf相加溢出)

    题目链接 题意:给你一个树形图,让你把其中若干个结点染成黑色,其余的染成白色,使得任意一个白色结点都恰好与一个黑色结点相邻. 解法比较容易,和树上的最大独立集类似,取一个结点作为树根,对每个结点分三种 ...

  2. UVa 1218 - Perfect Service

    /*---UVa 1218 - Perfect Service ---首先对状态进行划分: ---dp[u][0]:u是服务器,则u的子节点可以是也可以不是服务器 ---dp[u][1]:u不是服务器 ...

  3. UVA - 1218 Perfect Service (树形DP)

    思路:dp[i][0]表示i是服务器:dp[i][1]表示i不是服务器,但它的父节点是服务器:dp[i][2]表示i和他的父亲都不是服务器.       转移方程: d[u][0] += min(d[ ...

  4. UVa 1218 - Perfect Service(树形DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  5. UVa 1218 Perfect Service 完美的服务

    ***状态设计值得一看dp[u][0]表示u是服务器(以下v均指任意u的子结点,son指u的所有子结点)ap[u][0]=sum{dp[v][1]}+1//错误,服务器是可以和其他服务器相邻的dp[u ...

  6. POJ3398Perfect Service[树形DP 树的最大独立集变形]

    Perfect Service Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1518   Accepted: 733 De ...

  7. UVa 10859 - Placing Lampposts 树形DP 难度: 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  8. UVa 1292 - Strategic game (树形dp)

    本文出自   http://blog.csdn.net/shuangde800 题目链接: 点击打开链接 题目大意 给定一棵树,选择尽量少的节点,使得每个没有选中的结点至少和一个已选结点相邻. 思路 ...

  9. Uva LA 3902 - Network 树形DP 难度: 0

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

随机推荐

  1. .net 导出带条码的PDF

    Nuget添加引用:ZXing.Net生成条形码,ZXing.Net.Bindings.ImageSharp生成图片 将图片流插入单元格 举个栗子: BarcodeWriter writer = ne ...

  2. Scrum 思考

    下个月就要离职,所以这个月特别清闲,上班时间都在上网看书,偶然在Startup News的一篇文章(http://blog.devtang.com/blog/2013/06/17/startup-an ...

  3. go语言基础之defer延迟调用

    1.defer作用 关键字 defer ⽤于延迟一个函数或者方法(或者当前所创建的匿名函数)的执行.注意,defer语句只能出现在函数或方法的内部. 运行场景: defer语句经常被用于处理成对的操作 ...

  4. 移植tslib和Qt5.6到三星s5pv210开发板

    tslib1.4移植 下载tslib1.4后 1.cp tslib-1.4.tar.bz2 /home/gec 2.tar jxvf tslib-1.4.tar.bz2 3.sudo -s 4.cd ...

  5. 一个十分简洁实用的MD风格的UI主框架

    2017-5-23 详见:https://github.com/baiqiantao/CheesesquareSample MainActivity public class MainActivity ...

  6. 根据Ip地址与掩码 得出 子网地址与广播地址

    由于给予条件优先,没有直接给出子网地址与广播地址.但是又需要这两个参数,需要我们使用ip 地址与 子网掩码得出子网地址与广播地址.思路如下:       1. 子网地址, ip地址与 子网掩码分别换算 ...

  7. ASP站点无法访问怎么办

    确保启用了目录浏览功能

  8. setsockopt之 TCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT

    setsockopt之 TCP_KEEPIDLE/TCP_KEEPINTVL/TCP_KEEPCNT /*检测网线非法断开*/    setsockopt(iSockFd, SOL_SOCKET, S ...

  9. Linux cmp命令——比较二进制文件(转)

    Linux cmp命令用于比较两个文件是否有差异. 当相互比较的两个文件完全一样时,则该指令不会显示任何信息.若发现有所差异,预设会标示出第一个不同之处的字符和列数编号.若不指定任何文件名称或是所给予 ...

  10. 控制器中添加DB类才可以操作数据库表中的数据

    必须使用DB:  use DB;