treecnt 51Nod - 1677
给定一棵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取模。
Sample Input
3 2 1 2 1 3
Sample Output
4
思路:
我们需要每次找K个点,那么对应我们可能有三种取法:
①在这条边的两侧都有点被取了出来
②只在左侧选K个点
③只在右侧选K个点
对应最后两种情况是没有贡献度的.那么对应去掉即可。
那么对应这条边的贡献度为:C(n,k)-C(x,k)-C(y,k);
因为需要取模,所以需要处理逆元。DFS求出点的子节点个数,然后带人公式中计算就行。
这样的题目,编程实现很简单,难在无法想出求解的办法,我觉得多积累经验才能想出来吧,天才如果没有经验,我觉得也不可能想出来。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <string>
#include <math.h>
#include <sstream>
#include <stack>
typedef long long ll;
const int INF=100000;
const int maxn=1e6+5;
const int MOD=1e9+7;
using namespace std;
int head[maxn];
ll n,k;
ll ans;
bool vis[maxn];
int edgeNum;
ll fac[maxn],inv_fac[maxn];
struct Edege
{int u,v,next;
}edge[maxn];
void AddEdge(int u,int v)
{edge[edgeNum].u=u;edge[edgeNum].v=v;edge[edgeNum].next=head[u];head[u]=edgeNum++;
}
ll qpow(ll a,ll b)
{ll ans=1;while(b){if(b&1){ans=ans*a%MOD;}b>>=1;a=a*a%MOD;}return ans;
}
void init()
{fac[1]=1;for(int i=2;i<=maxn;i++){fac[i]=fac[i-1]*1ll*i%MOD;}inv_fac[maxn]=qpow(fac[maxn],MOD-2);for(int i=maxn-1;i>=0;i--){inv_fac[i]=inv_fac[i+1]*1ll*(i+1)%MOD;}
}
ll C(int a,int b)
{if(b>a) return 0;if(b==0) return 1;return fac[a]*inv_fac[b]%MOD*inv_fac[a-b]%MOD;
}
ll dfs(int s)
{vis[s]=1;ll cnt=1;for(int i=head[s];i!=-1;i=edge[i].next){int v=edge[i].v;if(vis[v]==1) continue;ll tmp=dfs(v);ans=(ans+(C(n,k)%MOD-C(tmp,k)%MOD-C(n-tmp,k)%MOD)%MOD+MOD)%MOD;cnt=(cnt+tmp)%MOD;}return cnt;
}
int main(int argc, char const *argv[])
{init();while(cin>>n>>k){edgeNum=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);AddEdge(x,y);AddEdge(y,x);}ans=0;dfs(1);cout<<(ans+MOD)%MOD<<endl;}return 0;
}
treecnt 51Nod - 1677相关推荐
- 51Nod 1677 treecnt
容斥 按照套路,按边考虑.一条边能贡献的答案是选的k个点分居两侧的方案数.发现这东西很难求.于是转成容斥求k个点归于一侧的方案数. #include<cstdio> #define N 1 ...
- 51nod 1677——treecnt
题意:给你n个结点,n-1条边,要从这n个结点里面选出k个结点,再选出最少边使这些结点之间相互连通,问对于所有选择k个结点的最小选择边数的总和是多少. 题解:因为每次选k个点其实是固定了的,所以撇开要 ...
- 1677 treecnt(贡献)
1677 treecnt 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 给定一棵n个节点的树,从1到n标号.选择k个点,你需要选择一些边使得这k个点通过选择的边联 ...
- 51nod 1617 奇偶数组
传送门 回来看一眼51nod,发现自己掉到rank4了,赶紧切道题回rank3. 一眼不会做,这种东西应该慢慢找规律吧--然后看到数据范围其实比较小,应该是单次log的,那是不是可以分治啊. #inc ...
- 1677: [Usaco2005 Jan]Sumsets 求和
1677: [Usaco2005 Jan]Sumsets 求和 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 626 Solved: 348 [Sub ...
- 51NOD 1773:A国的贸易——题解
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1773 参考1:FWT讲解 https://www.cnblogs.com ...
- 51nod 1040:最大公约数之和(数论)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1040 给出一个n,求1-n这n个数,同n的最大公约数的和. ...
- (DP)51NOD 1183 编辑距离
编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除 ...
- 斜率小于0的连线数量 51Nod - 1107 (树状数组+离散化)
二维平面上N个点之间共有C(n,2)条连线.求这C(n,2)条线中斜率小于0的线的数量. 二维平面上的一个点,根据对应的X Y坐标可以表示为(X,Y).例如:(2,3) (3,4) (1,5) (4, ...
最新文章
- js转换html为pdf文件怎么打开方式,pdf.js实现在HTML下直接浏览pdf文档,无需插件即可实现...
- gevent.hub.LoopExit: ('This operation would block forever
- redux模块化demo
- java创建日程到期提醒_Mac用户必备日程时间管理器,有计划有效率的人生才算完美!...
- [数据结构-严蔚敏版]P48栈的链式表示
- 51 Nod 1116 K进制下的大数
- WPF 浏览文件夹,获取其路径
- Chrome 扩展工具及命令
- Android 存储学习之SQLite数据库的基本操作
- Windowsmobile 的第一篇 为什么选择windows mobile 的分析
- word公式编号问题
- 【RNN】基于RNN的动态系统参数辨识matlab仿真
- 【无标题】有向图的创建、求度和遍历
- OpenCV的viz库学习(一)
- Xilinx RFSOC GEN1 ADC和DAC简单测试
- MySQL5.7 固态盘性能设置_MySQL 5.7 安装完成后,立即要调整的性能选项
- win7 wifi 共享 设置方法
- 使用低代码平台 - 危险的赌注
- QQ邮箱获取邮件客户端授权码
- Iphone6S 换屏教程
热门文章
- 前端如何判断用户是否打开了控制台
- 各种设计模式应用场景
- @Value取不到值的原因
- 深度学习中,偏置(bias)在什么情况下可以要,可以不要?
- 产品定位的原则,与同类产品竞争原则、拾遗补缺原则等5个方面
- 如何进行产品定位(上)
- 360html怎么保存,360浏览器网页怎么保存电脑桌面上
- 【uniapp】 读取手机通讯录权限
- 华为手机连电脑当摄像头用_今天才知道,华为手机摄像头还能这样用!还不会用你买什么华为?...
- [图论]---[网络流]---最小点割数/最小点割集