题目是求一棵n节点树中对于C(n,k)颗子树,每棵子树为在n个节点中选不同的k个节点作为树的边界点,这样的所有子树共包含多少条边。

问题可以转化一下,对每一条边,不同的子树中可能包含可能不包含这条边,显然,只有子树那k个节点在该边的两侧均有分布时该边才被包含在子树中。所有边的被包含次数的和,即为answer。对于一条边的被包含次数,设该边两侧分别有a,b个节点,那么,该边被包含的次数为C(a+b,k)-C(a,k)-C(b,k)(也可以借助母函数函数求C(a,i)*C(b,k-i),i从1到min{a,b,k-1},结果一样)。

//dfs写的太搓了,调了半天才好。。。

题目链接

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef long long LL;
  5. const LL mod=1e9+;
  6. const LL M=1e5+;
  7.  
  8. LL fac[]; //阶乘
  9. LL inv_of_fac[]; //阶乘的逆元
  10.  
  11. LL qpow(LL x,LL n)
  12. {
  13. LL ret=;
  14. for(; n; n>>=)
  15. {
  16. if(n&) ret=ret*x%mod;
  17. x=x*x%mod;
  18. }
  19. return ret;
  20. }
  21. void init()
  22. {
  23. fac[]=;
  24. for(int i=; i<=M; i++)
  25. fac[i]=fac[i-]*i%mod;
  26. inv_of_fac[M]=qpow(fac[M],mod-);
  27. for(int i=M-; i>=; i--)
  28. inv_of_fac[i]=inv_of_fac[i+]*(i+)%mod;
  29. }
  30. LL C(LL a,LL b)
  31. {
  32. if(b>a) return ;
  33. if(b==) return ;
  34. return fac[a]*inv_of_fac[b]%mod*inv_of_fac[a-b]%mod;
  35. }
  36. /////////////////////////////////////////////////////////////
  37. vector<int> adj[M];
  38. int vis[M];
  39. LL n,k,ans,du[M],hh;
  40. void init1()
  41. {
  42. ans=;
  43. memset(vis,,sizeof(vis));
  44. memset(du,,sizeof(du));
  45. du[]=n;
  46. hh=C(n,k);
  47. for(int i=; i<=n; i++)
  48. adj[i].clear();
  49. }
  50. LL dfs(int s)
  51. {
  52. if(adj[s].size()==&&s!=) return du[s]=;
  53. if(du[s]&&s!=) return du[s];
  54. vis[s]=;
  55. LL ret,cnt=;
  56. for(int i=; i<adj[s].size(); i++)
  57. {
  58. if(!vis[adj[s][i]])
  59. {
  60. // printf("%d -> %d\n",s,adj[s][i]);
  61. cnt+=dfs(adj[s][i]);
  62. ans=(ans+hh-C(dfs(adj[s][i]),k)-C(n-dfs(adj[s][i]),k))%mod;
  63. }
  64. }
  65. return du[s]=cnt+;
  66. }
  67.  
  68. int main()
  69. {
  70. init();
  71. while(~scanf("%lld%lld",&n,&k))
  72. {
  73. init1();
  74. for(int i=; i<n; i++)
  75. {
  76. LL u,v;
  77. scanf("%d%d",&u,&v);
  78. adj[u].push_back(v);
  79. adj[v].push_back(u);
  80. }
  81. dfs();
  82. // for(int i=1; i<=n; i++)
  83. // printf("%d:%lld=========\n",i,du[i]);
  84. // for(int i=1; i<=n; i++)
  85. // {
  86. // printf("i=%d:\n",i);
  87. // for(int j=0; j<adj[i].size(); j++)
  88. // printf("%d ",adj[i][j]);
  89. // puts("");
  90. // }
  91. printf("%lld\n",(ans+mod)%mod);
  92. }
  93. }

// 2017.8.15 更

回头翻一下之前自己写的博客,发现连个dfs都写这么挫,就算这样居然也有人看。重新改了一下代码贴在下面。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. typedef long long LL;
  5. const LL mod=1e9+;
  6. const LL M=1e5+;
  7.  
  8. LL fac[M+]; //阶乘
  9. LL inv_of_fac[M+]; //阶乘的逆元
  10.  
  11. LL qpow(LL x,LL n)
  12. {
  13. LL ret=;
  14. for(; n; n>>=)
  15. {
  16. if(n&) ret=ret*x%mod;
  17. x=x*x%mod;
  18. }
  19. return ret;
  20. }
  21. void init()
  22. {
  23. fac[]=;
  24. for(int i=; i<=M; i++)
  25. fac[i]=fac[i-]*i%mod;
  26. inv_of_fac[M]=qpow(fac[M],mod-);
  27. for(int i=M-; i>=; i--)
  28. inv_of_fac[i]=inv_of_fac[i+]*(i+)%mod;
  29. }
  30. LL C(LL a,LL b)
  31. {
  32. if(b>a) return ;
  33. if(b==) return ;
  34. return fac[a]*inv_of_fac[b]%mod*inv_of_fac[a-b]%mod;
  35. }
  36. /////////////////////////////////////////////////////////////
  37. vector<int> adj[M];
  38. LL n,k,ans,hh;
  39. void init1()
  40. {
  41. ans=;
  42. hh=C(n,k);
  43. for(int i=; i<=n; i++)
  44. adj[i].clear();
  45. }
  46.  
  47. LL dfs(int s,int pre)
  48. {
  49. LL ret=;
  50. for(int i=; i<adj[s].size(); i++)
  51. {
  52. if(adj[s][i]==pre) continue;
  53. LL t=dfs(adj[s][i],s);
  54. ret+=t;
  55. ans=(ans+hh-C(t,k)-C(n-t,k))%mod;
  56. }
  57. return ret;
  58. }
  59.  
  60. int main()
  61. {
  62. init();
  63. while(~scanf("%lld%lld",&n,&k))
  64. {
  65. init1();
  66. for(int i=; i<n; i++)
  67. {
  68. LL u,v;
  69. scanf("%d%d",&u,&v);
  70. adj[u].push_back(v);
  71. adj[v].push_back(u);
  72. }
  73. dfs(,-);
  74. printf("%lld\n",(ans+mod)%mod);
  75. }
  76. }

51nod_1677:treecnt的更多相关文章

  1. treecnt

    treecnt  ﹡    LH (命题人)   基准时间限制:1 秒 空间限制:131072 KB 分值: 40 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择 ...

  2. 树上统计treecnt(dsu on tree 并查集 正难则反)

    题目链接 dalao们怎么都写的线段树合并啊.. dsu跑的好慢. \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\( ...

  3. [洛谷U40581]树上统计treecnt

    [洛谷U40581]树上统计treecnt 题目大意: 给定一棵\(n(n\le10^5)\)个点的树. 定义\(Tree[l,r]\)表示为了使得\(l\sim r\)号点两两连通,最少需要选择的边 ...

  4. 1677 treecnt(贡献)

    1677 treecnt 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联 ...

  5. treecnt 算法马拉松20(告别美国大选及卡斯特罗)

    treecnt 基准时间限制:1 秒 空间限制:131072 KB 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联通,目标是使得选择的边数最少. 现需要计算 ...

  6. 51Nod 1677 treecnt

    一道比较基础的计数题,还是一个常用的单独计算贡献的例子. 首先看题目和范围,暴力枚举肯定是不可行的,而且\(O(n\ logn)\)的算法貌似很难写. 那我们就来想\(O(n)\)的吧,我们单独考虑每 ...

  7. 51nod 1677 treecnt(思维)

    题意: 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联通,目标是使得选择的边数最少. 现需要计算对于所有选择k个点的情况最小选择边数的总和为多少. 考虑每条 ...

  8. 【51nod1677】treecnt(树上数学题)

    点此看题面 大致题意: 给你一个节点从1~n编号的树,让你从中选择k个节点并通过选择的边联通,且要使选择的边数最少,让你计算对于所有选择k个节点的情况最小选择边数的总和. 题解 这道题乍一看很麻烦:最 ...

  9. 【计数】51nod1677 treecnt

    要将答案看做是小问题的贡献和 Description 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联通,目标是使得选择的边数最少. 现需要计算对于所有选择k ...

随机推荐

  1. 安卓餐厅点餐系统---针对浩然android工作室的一个小白的分析

    昨天刚把浩然android工作室的下载下来了,为了研究下点餐系统的架构,更好的完成手中的项目,便写出一个分析报告(小白的分析,忘见谅!) 本项目app主要用于餐厅无线订餐使用,功能突出餐厅的订餐需求, ...

  2. Day1 - Python基础1 Python介绍、基本语法、流程控制习题集

    1.打印Hello World! print("Hello World!") 或 name="你好,世界!" print(name) 2.声明变量:打印name ...

  3. Vue基础概念,学习环境等

    前提: 你已有 HTML.CSS 和 JavaScript 中级前端知识. 概念: Vue.js(读音 /vjuː/,类似于 view) 是一套构建用户界面的渐进式框架.与其他重量级框架不同的是,Vu ...

  4. webpack 插件拾趣 (1) —— webpack-dev-server

    结束了一季的忙碌,我这封笔已久的博客也终究该从春困的咒印中复苏,想来写些实用易读的作为开篇,自然是最好不过. 新开个 webpack 插件/工具介绍的文章系列,约莫每周更新一篇篇幅适中的文章聊以共勉, ...

  5. python基础之字典dict和集合set

    作者:tongqingliu 转载请注明出处:http://www.cnblogs.com/liutongqing/p/7043642.html python基础之字典dict和集合set 字典dic ...

  6. BOM API

    原文链接http://www.jb51.net/article/55851.htm 我们都知道, javascript 有三部分构成,ECMAScript,DOM和BOM,根据宿主(浏览器)的不同,具 ...

  7. 【转载】Static 关键字的作用

    原始日期:2016-07-16 17:53   一   普通的static关键字 1.  静态全局变量 在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量.我们先举一个静态全局变 ...

  8. phpcms和php格式化时间戳

    用PHPCMS V9 建站时,经常会用到时间标签,它是通用标签调用-日期时间格式化,适用全站. 一.日期时间格式化显示: a\标准型:{date('Y-m-d H:i:s', $rs['inputti ...

  9. 基于node.js制作爬虫教程

    前言:最近想学习node.js,突然在网上看到基于node的爬虫制作教程,所以简单学习了一下,把这篇文章分享给同样初学node.js的朋友. 目标:爬取 http://tweixin.yueyishu ...

  10. linux下安装telnet

    1:yum install telnet-server 2:编辑设置 /etc/xinetd.d/telnet ,将disable= yes设置成disable= no 3:service  xine ...