jzoj4887 最大匹配
2016-11-26 15:39
295 查看
问题描述
现在给你一个N个点N-1条边的连通图,希望你能够求出这个图的最大匹配以及最大匹配的数量。两个匹配不同当且仅当存在一条边在第一个匹配中存在而在第二个匹配中不存在。
若p=1,则一行一个数输出图的最大匹配
若p=2,则一行两个数输出图的最大匹配以及最大匹配数量,答案对10^9+7取模。
比赛时过了p=1+暴力的60分
解
首先不难求出最大匹配.设Gi,0/1分别为这个点有没有被占用的最大匹配.
其中j是i的子节点
G[i,0]=∑max(G[j,1],G[j,0]).
G[i,1]=max(G[j,0](i与j这条边选入)+∑max(G[j′,1],G[j′,0])(其他照常))+1
然后max(g[1,0],g[1,1])就是第一问的答案.
对于第二问,我们设Fi,0/1分别为当这个点被占用/没被占用,且最大匹配等于对应的G的时候的方案数.
再用y(j)表示节点i对应选最大的方案数,要是Gi,0大那么就是Fi,0,要是Gi,1大那么就是Fi,1,若相等则为二者之和.
F[i,0]=∏y(j)
其中z是能够使得G[i,1]最大的j的集合中的任意一个.
因为我们要保证他的匹配必须是最大的.局部最大才能推出全局最大.
F[i,1]=∑(F[z,0](这条边入选)∗∏y(j)(其他照常))
这样话,y(1)即为答案.
打的时候错误比较多,因为方程有点诡异..
#include <cstdio> #include <iostream> #include <cstring> #define maxn 100010 #define mo 1000000007 #define max(a,b) ((a)>(b)?(a):(b)) #define inver(x) (qf(x,mo-2)) using namespace std; typedef long long ll; ll from[maxn*2],to[maxn*2],next[maxn*2],head[maxn],tot,g[maxn][2],f[maxn][2],vis[maxn]; ll t,n,p,ans2,ans1; ll qf(ll x,ll y) { if (y==0) return 1; if (y==1) return x; ll tmp=qf(x,y>>1); return tmp*tmp%mo*qf(x,y&1)%mo; } ll rec(ll tt){ if (g[tt][0]==g[tt][1]) return f[tt][0]+f[tt][1]; return (g[tt][0]>g[tt][1])?f[tt][0]:f[tt][1]; } void dfs(ll x,ll fa) { ll t,si=0,sum=0,ma=0,can=1; f[x][0]=1; for (int k=head[x]; k; k=next[k]) { t=to[k]; if (t==fa) continue; si=1; dfs(t,x); sum+=g[t][1]; can=can*rec(t)%mo; f[x][0]=f[x][0]*rec(t)%mo; } if (si==0) { g[x][0]=0,g[x][1]=0; f[x][0]=1,f[x][1]=0; return; } for (int k=head[x]; k; k=next[k]) { t=to[k]; if (t==fa) continue; g[x][0]+=max(g[t][1],g[t][0]); if (sum-g[t][1]+g[t][0]>ma) ma=sum-g[t][1]+g[t][0]; } for (int k=head[x]; k; k=next[k]) { t=to[k]; if (t==fa) continue; if (sum-g[t][1]+g[t][0]==ma) f[x][1]=(f[x][1]+f[t][0]*(can*inver(rec(t))%mo)%mo)%mo; } g[x][1]=ma+1; } void link(int a,int b) { to[++tot]=b; from[tot]=a; next[tot]=head[a]; head[a]=tot; } int main() { freopen("hungary.in","r",stdin); //freopen("hungary.out","w",stdout); for (cin>>t>>p; t; t--) { memset(g,0,sizeof g); memset(f,0,sizeof f); memset(next,0,sizeof next); memset(to,0,sizeof to); memset(head,0,sizeof head); tot=0; cin>>n; int a,b; for (int i=1; i<n; i++) { scanf("%d %d",&a,&b); link(a,b); link(b,a); } dfs(1,0); ans1=max(g[1][0],g[1][1]); cout<<ans1<<" "; if (p==2) cout<< rec(1)%mo; cout<<endl; } }
相关文章推荐
- 【JZOJ4887】【NOIP2016提高A组集训第13场11.11】最大匹配
- 【jzoj4887】【最大匹配】【树形动态规划】
- 【JZOJ 4887】最大匹配
- [jzoj]3457. 【NOIP2013模拟联考3】沙耶的玩偶(doll)(匈牙利-二分图最大匹配)
- JZOJ4887. 【NOIP2016提高A组集训第13场11.11】最大匹配
- [JZOJ 1280]最大匹配
- HDU 3395 Special Fish 二分匹配(求最大匹配值)
- Dolls hdu 4160 匈牙利算法求出最大匹配值
- hdu2444二分图判定 + 最大匹配
- 【UOJ#79】一般图最大匹配(带花树)
- Konig定理:最大匹配==最小顶点覆盖
- 证明二分图最大匹配=二分图最小点集覆盖
- POJ二分图最大匹配的简单题目
- hdu3315 /最大权最佳匹配(最大权下尽量不改变次序)(有权田忌赛马类问题)/费用流
- hdu 2063 过山车(二分图最大匹配)
- codeforces 387D George and Interesting Graph(二分图最大匹配)
- POJ 2112 Optimal Milking 二分+二分图多重匹配,网络最大流
- Java正则表达式最大,最小匹配
- uva 1045(二分图最大权匹配)
- poj 3020 Antenna Placement(二分图的最大匹配)