• 10.26T2 树形DP


    #3857 最大匹配

    描述

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

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

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

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

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

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

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

    输入

    第一行两个数T,P,其中T表示数据组数。

    接下来每组数据第一行一个数N

    接下来N-1行每行两个数分别表示一条边。

    输出

    对于每组数据,输出一行;

    若p=1,则一行一个数输出图的最大匹配

    若p=2,则一行两个数输出图的最大匹配以及最大匹配数量,答案对10^9+7取模。

    样例输入[复制]
    1 1
    2
    1 2
    样例输出[复制]
    1
    提示
    20181026153636_60601
     
     
     
     
    第一问我写的全部点减去最大独立点集导致不能做第二问
    粘个官方题解
     
    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

  • 相关阅读:
    百度地图API地理位置和坐标转换
    解决Myeclipse中导入自定义的配色方案后,JSP中的js代码块为白色背景的问题
    Windows 平台下Myeclipse 10 中SVN 插件使用教程(TortoiseSVN)
    Java代码通过API操作HBase的最佳实践
    HBase中多Filter查询示例
    使用Ant编译和构建项目指南
    如何在Google Play商店发布多个版本apk
    Android 设备管理API概览(Device Administration API)
    Android呼叫管理服务之会话发起协议(SIP)API
    Android基础知识之String类使用详解
  • 原文地址:https://www.cnblogs.com/saionjisekai/p/9858465.html
Copyright © 2020-2023  润新知