要将答案看做是小问题的贡献和

Description

给定一棵n个节点的树,从1到n标号。选择k个点,你需要选择一些边使得这k个点通过选择的边联通,目标是使得选择的边数最少。

现需要计算对于所有选择k个点的情况最小选择边数的总和为多少。
样例解释:

一共有三种可能:(下列配图蓝色点表示选择的点,红色边表示最优方案中的边)

选择点{1,2}:至少要选择第一条边使得1和2联通。

 

选择点{1,3}:至少要选择第二条边使得1和3联通。

选择点{2,3}:两条边都要选择才能使2和3联通。

Input

第一行两个数n,k(1<=k<=n<=100000)
接下来n-1行,每行两个数x,y描述一条边(1<=x,y<=n)

Output

一个数,答案对1,000,000,007取模。

Input示例

3 2
1 2
1 3

Output示例

4

题目分析

初看上去好像要结合树形结构做一些麻烦的事情……例如判断树中长度为k的连通块个数之类的。

但是实际上问题可以看做是每一条边对于答案贡献了$si$,答案就是$\sum{si}$。

那么单独的贡献自然应该是选择了横跨这条边的两个点的情况。

这里就考虑一下问题的反面:选择了不横跨这条边的情况,应该是$C_{u_{size}}^{k}+C_{v_{size}}^{k}$,其中$u_{size}$和$v_{size}$分别表示这条边两边有多少个点。

于是就愉快地解决这题了。

 #include<bits/stdc++.h>
typedef long long ll;
const ll MO = ;
const int maxn = ;
const int maxm = ; ll fac[maxn],facinv[maxn],ans,sum;
int n,k;
int size[maxn];
int edges[maxm],nxt[maxm],head[maxn],edgeTot; int read()
{
char ch = getchar();
int num = ;
bool fl = ;
for (; !isdigit(ch); ch = getchar())
if (ch=='-') fl = ;
for (; isdigit(ch); ch = getchar())
num = (num<<)+(num<<)+ch-;
if (fl) num = -num;
return num;
}
void addedge(int u, int v)
{
edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
edges[++edgeTot] = u, nxt[edgeTot] = head[v], head[v] = edgeTot;
}
void dfs1(int x, int fa)
{
size[x] = ;
for (int i=head[x]; i!=-; i=nxt[i])
if (edges[i]!=fa) dfs1(edges[i], x), size[x] += size[edges[i]];
}
ll c(ll n, ll m){return n < m?:fac[n]*facinv[n-m]%MO*facinv[m]%MO;}
void dfs2(int x, int fa)
{
for (int i=head[x]; i!=-; i=nxt[i])
{
int v = edges[i];
if (fa==v) continue;
ans = (ans+sum-c(size[v], k)-c(n-size[v], k))%MO;
dfs2(v, x);
}
}
int main()
{
memset(head, -, sizeof head);
n = read(), k = read(), fac[] = facinv[] = facinv[] = ;
for (int i=; i<n; i++) addedge(read(), read());
for (int i=; i<=n; i++) facinv[i] = (MO-MO/i)*facinv[MO%i]%MO;
for (int i=; i<=n; i++)
fac[i] = (fac[i-]*i)%MO, facinv[i] = facinv[i]*facinv[i-]%MO;
sum = c(n, k);
dfs1(, );
dfs2(, );
printf("%lld\n",(ans+MO)%MO);
return ;
}

END

【计数】51nod1677 treecnt的更多相关文章

  1. NOIP2018 - 暑期博客整理

    暑假写的一些博客复习一遍.顺便再写一遍或者以现在的角度补充一点东西. 盛暑七月 初涉基环外向树dp&&bzoj1040: [ZJOI2008]骑士 比较经典的基环外向树dp.可以借鉴的 ...

  2. 【树形背包】bzoj4033: [HAOI2015]树上染色

    仔细思考后会发现和51nod1677 treecnt有异曲同工之妙 Description 有一棵点数为N的树,树边有边权.给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并 ...

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

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

  4. 计数排序(counting-sort)——算法导论(9)

    1. 比较排序算法的下界 (1) 比较排序     到目前为止,我们已经介绍了几种能在O(nlgn)时间内排序n个数的算法:归并排序和堆排序达到了最坏情况下的上界:快速排序在平均情况下达到该上界.   ...

  5. Objective-C内存管理之引用计数

    初学者在学习Objective-c的时候,很容易在内存管理这一部分陷入混乱状态,很大一部分原因是没有弄清楚引用计数的原理,搞不明白对象的引用数量,这样就当然无法彻底释放对象的内存了,苹果官方文档在内存 ...

  6. 最小生成树计数 bzoj 1016

    最小生成树计数 (1s 128M) award [问题描述] 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一 ...

  7. swift学习笔记5——其它部分(自动引用计数、错误处理、泛型...)

    之前学习swift时的个人笔记,根据github:the-swift-programming-language-in-chinese学习.总结,将重要的内容提取,加以理解后整理为学习笔记,方便以后查询 ...

  8. [LeetCode] Count and Say 计数和读法

    The count-and-say sequence is the sequence of integers beginning as follows:1, 11, 21, 1211, 111221, ...

  9. C++ 引用计数技术及智能指针的简单实现

    一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 1.智能指针是什么 简单来说,智能指针是一个类,它对普 ...

随机推荐

  1. Django框架知识2

    1.Http消息格式: 1.请求(request): 请求方法 请求路径 HTTP/1.1\r\n k1:v1\r\n k2:v2\r\n \r\n 请求体正文 2.响应(response) HTTP ...

  2. webpack结合vue使用(五)

    webpack结合vue使用步骤如下: 安装 vue 的包 : cnpm i vue -S 由于在 webpack 中,锐减使用 .vue 这个组件模板文件定义组件,所以需要安装能解析这种文件的第三方 ...

  3. [题解](折半搜索/高斯消元枚举自由元)BZOJ_1770_Lights

    状压,时间空间都不行,如果每次搜索一半就可以省下很多空间,用map记下每种状态的答案,最后再把两次的答案合并 然而正解是高斯消元解异或方程组,最后搜索自由元 #include<iostream& ...

  4. redis配置配置文件

    # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等酱紫: # # 1k => 1000 bytes # 1kb ...

  5. Tinghua Data Mining 4

    贝叶斯 决策树 知道三文鱼和金枪鱼颜色 让你去猜 B命中的概率不能直接减去四分之三 因为有可能同时命中 A B 命中不是互斥事件 即便体检报告是阳性,真正得癌症的概率也很小,只有0.21 绝大多数的阳 ...

  6. 洛谷P4288||bzoj3564 [SHOI2014]信号增幅仪

    bzoj3564 洛谷P4288 可以旋转一下坐标轴使得x轴与长轴方向对齐,然后将所有的横坐标变为自身除以放大倍数,然后就做一个最小圆覆盖 #include<cstdio> #includ ...

  7. datagridview连接数据库的简单实现

    对于需要从数据库获取数据的列,在DataPropertyName填写对应的列名字. 在Load函数中添加如下代码,先关闭自动生成列选项,然后得到一个查询的datatable,并将其绑定到datasou ...

  8. 配置Gradle构建

    构建基础配置 Android Studio包含一个顶级的构建文件和每个模块的构建文件.构建文件被称为 build.gradle,它是一个纯文本文件,它使用Groovy语法来配置由Android Gra ...

  9. 二叉查找树之AVL树

    定义平衡树节点: class TreeNode { /** * 树节点的值 */ private int val; /** * 树的高度 */ private int height; /** * 左子 ...

  10. Nginx 开启目录浏览功能配置

    在server节点下添加 server { listen ; server_name default; #index index.php; # 目录浏览功能 autoindex on; # 显示文件大 ...