#3857 最大匹配
描述
小C学习了二分图匹配,二分图是一种特殊的图,其中的点可以分到两个集合中,使得相同的集合中的点两两没有连边。
图的“匹配”是指这个图的一个边集,里面的边两两不存在公共端点。
匹配的大小是指该匹配有多少条边。
二分图匹配我们可以通过匈牙利算法得以在O(VE)时间复杂度内解决。
小C觉得单纯的二分图匹配算法毫无难度,因此提出新的问题:
现在给你一个N个点N-1条边的连通图,希望你能够求出这个图的最大匹配以及最大匹配的数量。
两个匹配不同当且仅当存在一条边在第一个匹配中存在而在第二个匹配中不存在。
输入
第一行两个数T,P,其中T表示数据组数。
接下来每组数据第一行一个数N
接下来N-1行每行两个数分别表示一条边。
输出
对于每组数据,输出一行;
若p=1,则一行一个数输出图的最大匹配
若p=2,则一行两个数输出图的最大匹配以及最大匹配数量,答案对10^9+7取模。
提示
第一问我写的全部点减去最大独立点集导致不能做第二问
粘个官方题解
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 1000006 5 using namespace std; 6 const long long mod=1e9+7; 7 struct node{ 8 long long u,v; 9 }e[N]; 10 long long first[N],nxt[N],cnt; 11 void add(long long u,long long v){ 12 e[++cnt].u=u; 13 e[cnt].v=v; 14 nxt[cnt]=first[u]; 15 first[u]=cnt; 16 } 17 long long f[N][2],rec[N],G[N][2]; 18 long long ksm(long long a,long long b){ 19 long long ans=1; 20 for(;b;b>>=1){ 21 if(b&1){ 22 ans*=a; 23 ans%=mod; 24 } 25 a*=a; 26 a%=mod; 27 } 28 return ans; 29 } 30 long long Val(int x){ 31 if(f[x][1]>f[x][0])return G[x][1]%mod; 32 if(f[x][1]<f[x][0])return G[x][0]%mod; 33 return (G[x][1]+G[x][0])%mod; 34 } 35 void DP(long long x,long long father){ 36 G[x][0]=1,G[x][1]=0; 37 for(long long i=first[x];i;i=nxt[i]){ 38 long long v=e[i].v; 39 if(v==father)continue; 40 DP(v,x); 41 f[x][0]+=max(f[v][0],f[v][1])%mod; 42 if(f[v][0]>f[v][1]){ 43 G[x][0]*=G[v][0]; 44 G[x][0]%=mod; 45 } 46 else if(f[v][0]<f[v][1]){ 47 G[x][0]*=G[v][1]; 48 G[x][0]%=mod; 49 } 50 else if(f[v][0]==f[v][1]){ 51 G[x][0]*=(G[v][0]+G[v][1])%mod; 52 G[x][0]%=mod; 53 } 54 } 55 for(long long i=first[x];i;i=nxt[i]){ 56 long long v=e[i].v; 57 if(v==father)continue; 58 f[x][1]=max(f[x][1],f[x][0]-max(f[v][0],f[v][1])+f[v][0]+1); 59 } 60 for(long long i=first[x];i;i=nxt[i]){ 61 long long v=e[i].v; 62 if(v==father)continue; 63 if(f[x][1]==f[x][0]-max(f[v][0],f[v][1])+f[v][0]+1){ 64 G[x][1]=(G[x][1]+(G[v][0]*G[x][0]%mod*ksm(Val(v),mod-2))%mod)%mod; 65 } 66 } 67 } 68 void init(){ 69 memset(first,0,sizeof first); 70 memset(nxt,0,sizeof nxt); 71 memset(e,0,sizeof e); 72 memset(f,0,sizeof f); 73 memset(G,0,sizeof G); 74 memset(rec,0,sizeof rec); 75 cnt=0; 76 } 77 long long read(){ 78 long long x=0,f=1; 79 char c=getchar(); 80 while(!isdigit(c)){ 81 if(c=='-')f=-1; 82 c=getchar(); 83 } 84 while(isdigit(c)){ 85 x=(x<<3)+(x<<1)+c-'0'; 86 c=getchar(); 87 } 88 return x*f; 89 } 90 signed main(){ 91 // cout<<ksm(3,5); 92 // freopen("hungary.in","r",stdin); 93 long long T,P; 94 T=read(),P=read(); 95 while(T--){ 96 init(); 97 long long n;n=read(); 98 for(long long i=1;i<n;i++){ 99 long long a,b; 100 a=read(),b=read(); 101 add(a,b); 102 add(b,a); 103 } 104 DP(1,1); 105 cout<<max(f[1][0],f[1][1]); 106 if(P==2){ 107 cout<<" "; 108 if(f[1][0]>f[1][1])cout<<G[1][0]; 109 else if(f[1][0]<f[1][1])cout<<G[1][1]; 110 else cout<<(G[1][1]+G[1][0])%mod; 111 } 112 cout<<' '; 113 } 114 return 0; 115 }
over