题意:求一颗无向树的最小点覆盖。

本来一看是最小点覆盖,直接一下敲了二分图求最小割,TLE。

树形DP,叫的这么玄乎,本来是线性DP是线上往前\后推,而树形DP就是在树上,由叶子结点状态向根状态推。

dp[u][1/0]:表示,结点u,1:选择,0,:不选。dp值是以改点为根(目前为止,dfs遍历顺序自然决定了树的层)的已经选择点数,自然开始时不知道,对每个点,初值dp[u][0]=0、

dp[u][1]=1,回溯的时候:

1:dp[u][1]+=min(dp[v][1],dp[v][0]);该节点选择了,那么子节点可选可不选。

2:dp[u][0]+=dp[v][1];该节点没有选择,则其子节点必需选择。

  1. #include<iostream>
  2. #include<queue>
  3. #include<stack>
  4. #include<cstdio>
  5. #include<vector>
  6. using namespace std;
  7. int n;
  8. vector<vector<int> >v(100010);
  9. int vis[100010];
  10. int dp[100010][2];
  11. inline int minn(int a,int b)
  12. {
  13. if(a<b)return a;
  14. return b;
  15. }
  16. void dfs(int u)
  17. {
  18. dp[u][0]=0; //不放,0个
  19. dp[u][1]=1; //放一个,
  20. for(int i=0;i<v[u].size();i++)
  21. {
  22. int vv=v[u][i];
  23. if(!vis[vv])
  24. {
  25. vis[vv]=1;
  26. dfs(vv);
  27. dp[u][0]+=dp[vv][1]; //回溯时加上
  28. dp[u][1]+=minn(dp[vv][1],dp[vv][0]);
  29. }
  30. }
  31. }
  32. int main()
  33. {
  34. scanf("%d",&n);
  35. int tx,ty;
  36. for(int i=0;i<n-1;i++)
  37. {
  38. scanf("%d%d",&tx,&ty);
  39. v[tx].push_back(ty);
  40. v[ty].push_back(tx);
  41. }
  42. vis[1]=1;
  43. dfs(1);
  44. cout<<minn(dp[1][0],dp[1][1]); //结果为根放与不放的状态最小值
  45. return 0;
  46. }

666,求最优时候方案数,

多一个DP方程即可。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<vector>
  4. using namespace std;
  5. int n;
  6. vector<vector<int> >v(100020);
  7. int vis[100020];
  8. struct state
  9. {
  10. int light;
  11. int count;
  12. };
  13. state dp[100020][2];
  14. inline int minn(int a,int b)
  15. {
  16. if(a<b)return a;
  17. return b;
  18. }
  19. void dfs(int u)
  20. {
  21. dp[u][0].light=0; //不放,0个
  22. dp[u][1].light=1; //放一个,
  23. dp[u][0].count=dp[u][1].count=1;
  24. for(int i=0;i<v[u].size();i++)
  25. {
  26. int vv=v[u][i];
  27. if(!vis[vv])
  28. {
  29. vis[vv]=1;
  30. dfs(vv);
  31. dp[u][0].light+=dp[vv][1].light; //回溯时加上
  32. dp[u][1].light+=minn(dp[vv][1].light,dp[vv][0].light);
  33.  
  34. dp[u][0].count= dp[u][0].count*dp[vv][1].count%10007;
  35.  
  36. if(dp[vv][1].light<dp[vv][0].light)
  37. dp[u][1].count=dp[u][1].count*dp[vv][1].count%10007;
  38.  
  39. else if (dp[vv][1].light>dp[vv][0].light)
  40. dp[u][1].count=dp[u][1].count*dp[vv][0].count%10007;
  41.  
  42. else
  43. dp[u][1].count=dp[u][1].count*(dp[vv][0].count+dp[vv][1].count)%10007;
  44.  
  45. }
  46. }
  47. }
  48. int main()
  49. {
  50. int t;
  51. scanf("%d",&t);
  52. while(t--)
  53. {
  54. scanf("%d",&n);
  55. int tx,ty;
  56. for(int i=0;i<=n;i++)
  57. {
  58. v[i].clear();vis[i]=0;
  59. }
  60. for(int i=0;i<n-1;i++)
  61. {
  62. scanf("%d%d",&tx,&ty);
  63. v[tx].push_back(ty);
  64. v[ty].push_back(tx);
  65. }
  66. vis[1]=1;
  67. dfs(1);
  68. int ans1=minn(dp[1][0].light,dp[1][1].light); //结果为根放与不放的状态最小值
  69. if(dp[1][0].light<dp[1][1].light)
  70. {
  71. printf("%d %d\n",ans1,dp[1][0].count);
  72. }
  73. else if(dp[1][0].light>dp[1][1].light)
  74. {
  75. printf("%d %d\n",ans1,dp[1][1].count);
  76. }
  77. else
  78. {
  79. int ans2= (dp[1][0].count%10007+dp[1][1].count%10007)%10007;
  80. printf("%d %d\n",ans1,ans2);
  81. }
  82. }
  83. return 0;
  84. }

SPOJ 1479 +SPOJ 666 无向树最小点覆盖 ,第二题要方案数,树形dp的更多相关文章

  1. Strategic game(无向?)二分图最小点覆盖(Poj1463,Uva1292)

    原题链接 此题求二分图的最小点覆盖,数值上等于该二分图的最大匹配.得知此结论可以将图染色,建有向图,然后跑匈牙利/网络流,如下.然而... #include<iostream> #incl ...

  2. UVALive 4329 树状数组第二题

    大白书上的题目,比较巧妙的是其分析,为了求某个i点做裁判的时候的情况数,只要知道左边有多少比它小的记为ansc,右边有多少比它小的记为ansd,则总种数,必定为 ansc*(右边总数-ansd)+an ...

  3. HDU 1054 Strategic Game(最小点覆盖+树形dp)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106048#problem/B 题意:给出一些点相连,找出最小的点数覆盖所有的 ...

  4. HDU 1054 Strategic Game (最小点覆盖)【二分图匹配】

    <题目链接> 题目大意:鲍勃喜欢玩电脑游戏,特别是战略游戏,但有时他无法找到解决方案,速度不够快,那么他很伤心.现在,他有以下的问题.他必须捍卫一个中世纪的城市,形成了树的道路.他把战士的 ...

  5. LA 2038 Strategic game(最小点覆盖,树形dp,二分匹配)

    题意即求一个最小顶点覆盖. 对于没有孤立点的图G=(V,E),最大独立集+最小顶点覆盖= V.(往最大独立集加点) 问题可以变成求树上的最大独立集合. 每个结点的选择和其父节点选不选有关, dp(u, ...

  6. 【BZOJ2286】消耗战(虚树,DFS序,树形DP)

    题意:一棵N个点的树上有若干个关键点,每条边有一个边权,现在要将这些关键点到1的路径全部切断,切断一条边的代价就是边权. 共有M组询问,每组询问有k[i]个关键点,对于每组询问求出完成任务的最小代价. ...

  7. nyoj 237 游戏高手的烦恼 二分匹配--最小点覆盖

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=237 二分匹配--最小点覆盖模板题 Tips:用邻接矩阵超时,用数组模拟邻接表WA,暂时只 ...

  8. POJ训练计划3041_Asteroids(二分图/最小点覆盖=最大匹配)

    解题报告 http://blog.csdn.net/juncoder/article/details/38135053 题目传送门 题意: 给出NxN的矩阵,有M个点是障碍 每次仅仅能删除一行或者一列 ...

  9. CodeCraft-19 and Codeforces Round #537 (Div. 2) E 虚树 + 树形dp(新坑)

    https://codeforces.com/contest/1111/problem/E 题意 一颗有n个点的树,有q个询问,每次从树挑出k个点,问将这k个点分成m组,需要保证在同一组中不存在一个点 ...

随机推荐

  1. KeyValuePair的使用

    Dictionary<string, string> dc = new Dictionary<string, string>(); 前台页面: <div id=" ...

  2. 洛谷 P1514 引水入城

    这次不说闲话了,直接怼题 这道题用bfs其实并不难想,但比较困难的是怎么解决满足要求时输出蓄水厂的数量.其实就像其他题解说的那样,我们可以用bfs将它转化成一个区间覆盖问题,然后再进行贪心. 首先枚举 ...

  3. commons-logging 和log4j包下载 Spring根据XML配置文件生成对象

    需要用到Spring压缩包中的四个核心JAR包 beans .context.core 和expression 下载地址: https://pan.baidu.com/s/1qXLHzAW 以及日志j ...

  4. JS面试题--使用for循环打印1-10,每个数字出现的间隔约500ms

    又来刷面试题啦,哈哈. 要求:使用for循环打印1-10,每个数字出现的间隔约500ms. 分析:考察点--闭包,块级作用域 方式一.使用闭包+立即执行函数,自己当时的思路也是这样想的,但是,结果却没 ...

  5. 【转发】【linux】【ftp】CentOS 7.0安装配置Vsftp服务器

    adduser -d /var/www/android -g ftp -s /sbin/nologin ftp2 一.配置防火墙,开启FTP服务器需要的端口 CentOS 7.0默认使用的是firew ...

  6. failed to execute goal org.apache.maven.plugins:maven-archetype-plugin错误解决方法

    使用maven创建project时碰到如下错误: D:\codes\JSF>mvn archetype:create -DgroupId=com.tutorialspoint.test -Dar ...

  7. Luogu 2569 [SCOI2010]股票交易 (朴素动规转移 + 单调队列优化)

    题意: 已知未来 N 天的股票走势,第 i 天最多买进 as [ i ] 股每股 ap [ i ] 元,最多卖出 bs [ i ] 股每股 bp [ i ] 元,且每天最多拥有 Mp 股,且每两次交易 ...

  8. MIP求解方法总结

    *本文主要记录和分享学习到的知识,算不上原创 *参考文献见链接 本文主要简述了求解MIP问题的两大类(精确求解和近似求解),或者更细致地,三大类方法(精确算法,ε-近似算法和启发式算法).由于暂时不太 ...

  9. SVN如何避免冲突

    在团队开发时,必然会用到代码版本控制工具,比如SVN. 但是多人共同维护同一份代码,当对同一文件进行增删时,就可能造成冲突,如何尽可能避免冲突相当重要. 首先,每次,新建任何文档,都会修改项目文件,所 ...

  10. C#中何时使用dynamic

    背景:比如说,有一个方法,有很多参数,且有时候只需要其中的某几个参数,有时候需要使用全部,甚至有时候一个都不需要,这时候写一个长长的参数列表一点都不酷,且容易 出错,这时候就需要考虑C#的dynami ...