题目


mhy12345学习了二分图匹配,二分图是一种特殊的图,其中的点可以分到两个集合中,使得相同的集合中的点两两没有连边。
图的“匹配”是指这个图的一个边集,里面的边两两不存在公共端点。
匹配的大小是指该匹配有多少条边。
二分图匹配我们可以通过匈牙利算法得以在O(VE)时间复杂度内解决。
mhy12345觉得单纯的二分图匹配算法毫无难度,因此提出新的问题:
现在给你一个N个点N-1条边的连通图,希望你能够求出这个图的最大匹配以及最大匹配的数量。
两个匹配不同当且仅当存在一条边在第一个匹配中存在而在第二个匹配中不存在。

分析

设\(f_{i,0|1}\)表示,第i个节点,选了或不选的最大匹配,
设j为i的儿子,
\[f_{i,0}=\sum_jmax(f_{j,0},f_{j,1})\]
设k也是i的儿子,而j不包含k,
\[f_{i,1}=max(f_{k,0}+1+\sum max(f_{j,0},f_{j,1}))\ 将k与i匹配,剩下的取最大\]
接着考虑最大匹配数量,即方案数,
设\(g_{i,0|1}\)对于f这个状态最大匹配的方案数
设\[rec_{j}=\left\{\begin{array}\\g_{j,0}\ (f_{j,0}>f_{j,1})\\g_{j,1}\ (f_{j,0}<f_{j,1})\\g_{j,0}+g_{j,1}\ (f_{j,0}=f_{j,1})\end{array}\right.\]
\[g_{i,0}=\Pi rec_j\]
设k也是i的儿子,而j不包含k,并且\(f_{k,0}+1+\sum max(f_{j,0},f_{j,1})\)为最大值(或之一)
\[g_{i,1}=\sum(g_{k,0}·\Pi rec_j)\]
这个可以用逆元或者前缀积后缀积来处理。
发现其实\(f_{j,0}<=f_{j,1}\),
所以\(max(f_{j,0},f_{j,1})=f_{j,1}\)

```#include

include

include

include

include

include

include

const long long maxlongint=2147483647;
const long long mo=1000000007;
const long long N=100005;
using namespace std;
long long n,ans,t,p,rec[N],next[N*2],last[N*2],to[N*2],tot,f[N][2],g[N][2];
int bj(long long x,long long y)
{
next[++tot]=last[x];
last[x]=tot;
to[tot]=y;
}
long long mi(long long x,long long y)
{
long long sum=1;
while(y)
{
if(y&1) sum=sumx%mo;
x=x
x%mo;
y/=2;
}
return sum;
}
int dg(long long x,long long fa)
{
g[x][0]=g[x][1]=1;
f[x][0]=f[x][1]=rec[x]=0;
long long sumf=0,mir=1,q=1;
for(int i=last[x];i;i=next[i])
{
int j=to[i];
if(j!=fa)
{
dg(j,x);
sumf+=f[j][1];
f[x][0]+=f[j][1];
g[x][0]=g[x][0]rec[j]%mo;
mir=mir
rec[j]%mo;
q=false;
}
}
if(q) g[x][1]=0;
for(int i=last[x];i;i=next[i])
{
int j=to[i];
if(j!=fa)
{
if(f[x][1]<f[j][0]+1+sumf-f[j][1])
{
f[x][1]=f[j][0]+1+sumf-f[j][1];
g[x][1]=mirmi(rec[j],mo-2)%mog[j][0]%mo;
}
else
if(f[x][1]==f[j][0]+1+sumf-f[j][1])
{
g[x][1]=(g[x][1]+mirmi(rec[j],mo-2)%mog[j][0]%mo)%mo;
}
}
}
if(f[x][0]>f[x][1]) rec[x]=g[x][0];
else
if(f[x][0]<f[x][1]) rec[x]=g[x][1];
else rec[x]=g[x][0]+g[x][1];
}
int main()
{
scanf("%lld%lld",&t,&p);
while(t--)
{
tot=0;
memset(last,0,sizeof(last));
memset(next,0,sizeof(next));
scanf("%lld",&n);
for(long long i=1;i<=n-1;i++)
{
long long x,y;
scanf("%lld%lld",&x,&y);
bj(x,y);
bj(y,x);
}
dg(1,0);
printf("%lld ",max(f[1][0],f[1][1]));
if(p==2) printf("%lld",rec[1]%mo);
cout<<endl;
}
}

```

最新文章

  1. 解决SQL server 2014 修改表中的字段,无法保存的问题。
  2. js获取上一个月、下一个月格式为yyyy-mm-dd的日期
  3. BZOJ4546: codechef XRQRS
  4. SPOJ 227 Ordering the Soldiers 线段树 / 树状数组
  5. VK Cup 2012 Qualification Round 2 C. String Manipulation 1.0 字符串模拟
  6. MSSQLServer基础07(事务,存储过程,分页的存储过程,触发器)
  7. python3、selenium、autoit3,通过flash控件上传文件
  8. SplashScreenDemo
  9. Beautiful Soup常见的解析器
  10. SpringBoot/SpringMVC文件下载方式
  11. Docker 系列三(容器管理).
  12. GCH实践经验
  13. Java工程师学习指南 中级篇
  14. 基于【CentOS-7+ Ambari 2.7.0 + HDP 3.0】搭建HAWQ数据仓库 —— MariaDB 安装配置
  15. 轮滑基础(一)(前摔,葫芦步,推步,A字转弯,弓步转弯)
  16. 根据后台加载数据,添加loading动画
  17. 使用SVD方法实现电影推荐系统
  18. 【Leetcode】【Easy】Isomorphic Strings
  19. 开源 java CMS - FreeCMS2.2 建站向导
  20. codeforces——contest 864 problemE

热门文章

  1. 【SSM】---Spring+SpringMVC+Mybatis框架整合
  2. SpringMVC以POST提交表单中文乱码解决方案。
  3. P4995 跳跳!
  4. 【神经网络与深度学习】Caffe使用step by step:使用自己数据对已经训练好的模型进行finetuning
  5. vue --》elementUI 中 el-table组件 如何实现点击列,让该列高亮显示 ?
  6. vue--过滤器(私有,全局)
  7. AKKA学习(二) 未完
  8. eclipse中svn的使用
  9. [洛谷P4183][USACO18JAN]Cow at Large P
  10. dp入门题(数塔)