题目描述

mhy12345学习了二分图匹配,二分图是一种特殊的图,其中的点可以分到两个集合中,使得相同的集合中的点两两没有连边。

图的“匹配”是指这个图的一个边集,里面的边两两不存在公共端点。

匹配的大小是指该匹配有多少条边。

二分图匹配我们可以通过匈牙利算法得以在O(VE)时间复杂度内解决。

mhy12345觉得单纯的二分图匹配算法毫无难度,因此提出新的问题:

现在给你一个N个点N-1条边的连通图,希望你能够求出这个图的最大匹配以及最大匹配的数量。

两个匹配不同当且仅当存在一条边在第一个匹配中存在而在第二个匹配中不存在。

数据范围

分析与演绎

演绎直接得出树形动态规划。

设f[i]表示取i的最大匹配数,F[i]为这个情况下的方案数;

g[i]表示不取i的最大匹配数,G[i]为这个情况下的方案数。

转移方程显然。

代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define write(x) (cout<<(x))
#define writeln(x) (cout<<(x)<<endl)
#define ll long long
using namespace std;
const char* fin="hungary.in";
const char* fout="hungary.out";
const ll inf=0x7fffffff;
const ll maxn=100008,maxm=maxn*2,mo=1000000007;
ll t,m,n,i,j,k;
ll f[maxn],F[maxn],g[maxn],G[maxn],h[maxn],H[maxn];
ll fi[maxn],la[maxm],ne[maxm],tot=0;
void add_line(ll a,ll b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
ll read(){
ll x=0;
char ch=getchar();
while (ch<'0' && ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
ll qpower(ll a,ll b){
ll c=1;
while (b){
if (b&1) c=c*a%mo;
a=a*a%mo;
b>>=1;
}
return c;
}
ll N(ll a){
return qpower(a,mo-2);
}
void dfs(ll v,ll from){
ll i,j=0,k,sum=0,times=1;
f[v]=0;
F[v]=0;
g[v]=0;
G[v]=1;
for (k=fi[v];k;k=ne[k])
if (la[k]!=from){
dfs(la[k],v);
g[v]+=h[la[k]];
G[v]=G[v]*H[la[k]]%mo;
sum+=h[la[k]];
times=times*H[la[k]]%mo;
j=1;
}
for (k=fi[v];k;k=ne[k]){
if (la[k]!=from){
if (f[v]<sum-h[la[k]]+g[la[k]]+1){
f[v]=sum-h[la[k]]+g[la[k]]+1;
F[v]=times*N(H[la[k]])%mo*G[la[k]]%mo;
}else if (f[v]==sum-h[la[k]]+g[la[k]]+1) F[v]=(F[v]+times*N(H[la[k]])%mo*G[la[k]]%mo)%mo;
}
}
if (f[v]>g[v]) h[v]=f[v],H[v]=F[v];
else if (f[v]<g[v]) h[v]=g[v],H[v]=G[v];
else h[v]=f[v],H[v]=(F[v]+G[v])%mo;
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
t=read();
m=read();
while (t--){
tot=0;
memset(fi,0,sizeof(fi));
n=read();
for (i=1;i<n;i++){
j=read();
k=read();
add_line(j,k);
add_line(k,j);
}
dfs(1,0);
write(h[1]);
if (m==2) write(" "),write(H[1]);
write(endl);
}
return 0;
}

启发

写动态规划之前,一定要明确动态规划转移方程。

【JZOJ4887】【NOIP2016提高A组集训第13场11.11】最大匹配的更多相关文章

  1. 【NOIP2016提高A组集训第13场11.11】最大匹配

    题目 mhy12345学习了二分图匹配,二分图是一种特殊的图,其中的点可以分到两个集合中,使得相同的集合中的点两两没有连边. 图的"匹配"是指这个图的一个边集,里面的边两两不存在公 ...

  2. 【JZOJ4886】【NOIP2016提高A组集训第13场11.11】字符串

    题目描述 某日mhy12345在教同学们写helloworld,要求同学们用程序输出一个给定长度的字符串,然而发现有些人输出了一些"危险"的东西,所以mhy12345想知道对于任意 ...

  3. JZOJ 【NOIP2016提高A组集训第16场11.15】兔子

    JZOJ [NOIP2016提高A组集训第16场11.15]兔子 题目 Description 在一片草原上有N个兔子窝,每个窝里住着一只兔子,有M条路径连接这些窝.更特殊地是,至多只有一个兔子窝有3 ...

  4. JZOJ 【NOIP2016提高A组集训第16场11.15】SJR的直线

    JZOJ [NOIP2016提高A组集训第16场11.15]SJR的直线 题目 Description Input Output Sample Input 6 0 1 0 -5 3 0 -5 -2 2 ...

  5. 【JZOJ4824】【NOIP2016提高A组集训第1场10.29】配对游戏

    题目描述 流行的跳棋游戏是在一个有m*n个方格的长方形棋盘上玩的.棋盘起初全部被动物或障碍物占满了.在一个方格中,'X'表示一个障碍物,一个'0'-'9'的个位数字表示一个不同种类的动物,相同的个位数 ...

  6. 【NOIP2016提高A组集训第4场11.1】平衡的子集

    题目 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 分析 如果暴力枚举每个人被分到哪 ...

  7. 【JZOJ4841】【NOIP2016提高A组集训第4场11.1】平衡的子集

    题目描述 夏令营有N个人,每个人的力气为M(i).请大家从这N个人中选出若干人,如果这些人可以分成两组且两组力气之和完全相等,则称为一个合法的选法,问有多少种合法的选法? 数据范围 40%的数据满足: ...

  8. 【JZOJ4833】【NOIP2016提高A组集训第3场10.31】Mahjong

    题目描述 解法 搜索. 代码 #include<stdio.h> #include<iostream> #include<string.h> #include< ...

  9. 【NOIP2016提高A组集训第14场11.12】随机游走

    题目 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己是不 ...

随机推荐

  1. postfix+自签证书,实现加密传输

    说明:当前在centos 6.x环境下: cd /etc/pki/tls/misc ./CA -newca ..... 生成根证书 openssl req -new -nodes -keyout ma ...

  2. android 数据绑定(3)自动更新UI

    1.官方文档 https://developer.android.com/topic/libraries/data-binding/observability 2.observable 属性 适合对象 ...

  3. PHP1.9--数组

    1.array_slice()函数作用是在数组中根据条件取出一段值并返回,如果数组有字符串键,所返回的数组将保留健名 array array_slice(array array ,int offset ...

  4. TZ_16_Vue的v-model和v-on

    1.v-model是双向绑定,视图(View)和模型(Model)之间会互相影响. 既然是双向绑定,一定是在视图中可以修改数据,这样就限定了视图的元素类型.目前v-model的可使用元素有: inpu ...

  5. 接口--全局异常配置--异常处理handle自定义配置

    在重写了异常处理的handle类之后需要配置配置文件中handle的路径:

  6. ObservableCollection类

    https://blog.csdn.net/GongchuangSu/article/details/48832721 https://blog.csdn.net/hyman_c/article/de ...

  7. mysql查询 包含某个字符的记录

    从excel导入数据库的时候,发现poi自动把电话号码转换为科学计数法了 所以要把带e的筛选出来 SELECT * FROM t_customer WHERE phone like '%E%'; 然后 ...

  8. 根据一个分类id 获取这个分类底下所有子分类的商品信息,根据下面方法查询出所有有关分类id 再 根据这些id去商品表里查询所有商品信息

    /** * 检测该分类下所有子分类,并输出ID(包括自己) * 数据库字段 catid pid */ function getChildrenIds ($sort_id){ include_once ...

  9. 模拟7题解 T1方程的解

    方程的解 [扩展欧几里德] 首先进行特判,两个小时基本想到了,除了a!=0,b==0,a*c<0这种情况 其次就是一般情况: 首先exgcd求出ax+by=GCD(a,b)的一组任意解 然后两边 ...

  10. 隐马尔可夫模型及Viterbi算法

    隐马尔可夫模型(HMM,hidden Markov model)是可用于标注问题的统计学模型,描述由隐藏的马尔可夫链随机生成观测序列的过程,属于生成模型.HMM模型主要用于语音识别,自然语言处理,生物 ...