zoukankan      html  css  js  c++  java
  • [HNOI2015]实验比较 树形dp+组合数学

    在合并的时候有可以加等于,或者继续用小于,

    比如siz[x]和siz[y]合并,小于的区间为max(siz[x],siz[y])<=k<=siz[x]+siz[y],

    然后就是合并成多少个小于号的方案数了,

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<cstdlib>
      7 #define N 107
      8 #define M 207
      9 #define mod 1000000007
     10 #define ll long long
     11 using namespace std;
     12 
     13 int n,m,S;
     14 int cnt,head[N],next[M],rea[M];
     15 int fa[N],du[N],siz[N];
     16 bool boo[N],hash[N];
     17 struct Node
     18 {
     19     int x,y;
     20 }a[N];
     21 ll c[N][N],f[N][N],g[N],ans;
     22 
     23 void add(int u,int v)
     24 {
     25     next[++cnt]=head[u];
     26     head[u]=cnt;
     27     rea[cnt]=v,du[v]++;
     28 }
     29 int find(int num)
     30 {
     31     if (fa[num]!=num) fa[num]=find(fa[num]);
     32     return fa[num];
     33 }
     34 void dfs(int u,int fa)
     35 {
     36     boo[u]=1;bool flag=0;
     37     for (int i=head[u];i!=-1;i=next[i])
     38     {
     39         int v=rea[i];
     40         if (v==fa) continue;
     41         dfs(v,u);
     42         if (flag)
     43         {
     44             memset(g,0,sizeof(g));
     45             for (int i1=1;i1<=siz[u];i1++)
     46                 if (f[u][i1])
     47                 for (int j1=1;j1<=siz[v];j1++)
     48                     if (f[v][j1])
     49                     for (int k1=max(i1,j1);k1<=i1+j1;k1++)
     50                         g[k1]=(g[k1]+f[u][i1]*f[v][j1]%mod*c[k1][i1]%mod*c[i1][j1-(k1-i1)]%mod)%mod;
     51             siz[u]+=siz[v];
     52             for (int i=1;i<=siz[u];i++)
     53                 f[u][i]=g[i];            
     54         }
     55         else
     56         {
     57             flag=1;
     58             siz[u]=siz[v];
     59             for (int i=1;i<=siz[v];i++)
     60                 f[u][i]=f[v][i];
     61         }
     62     }
     63     if (u!=S)
     64     {
     65         siz[u]++;if (!flag) f[u][1]=1;
     66         else for (int i=siz[u];i>=1;i--) f[u][i]=f[u][i-1];
     67     }
     68 }
     69 bool dfs_circle(int u)
     70 {
     71     for (int i=head[u];i!=-1;i=next[i])
     72     {
     73         int v=rea[i];
     74         if (boo[v]) return false;
     75         boo[v]=true;
     76         if (!dfs_circle(v)) return false;
     77     }
     78     return true;
     79 }
     80 int main()
     81 {
     82     memset(head,-1,sizeof(head));
     83     scanf("%d%d",&n,&m);
     84     for (int i=1;i<=n;i++)
     85         fa[i]=i;
     86     for (int i=0;i<=n;i++)
     87         c[i][0]=1;
     88     for (int i=1;i<=n;i++)
     89         for (int j=1;j<=i;j++)
     90             c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
     91 //========================================================================================    
     92     int x,y,top=0;char ch[2];
     93     for (int i=1;i<=m;i++)
     94     {
     95         scanf("%d%s%d",&x,&ch,&y);
     96         if (ch[0]=='=')
     97         {
     98             int u=find(x),v=find(y);
     99             fa[v]=u;
    100             continue;
    101         }
    102         else if (ch[0]=='>') swap(x,y);
    103         a[++top].x=x,a[top].y=y;
    104     }
    105     m=top;
    106     for (int i=1;i<=m;i++)
    107     {
    108         int u=find(a[i].x),v=find(a[i].y);
    109         if (u!=v) add(u,v);//如果一个相等集合中有相互比较关系 
    110         else
    111         {
    112             printf("0
    ");
    113             return 0;
    114         }
    115     }
    116     for (int i=1;i<=n;i++)
    117         if (!boo[i])
    118         {
    119             boo[i]=1;
    120             if (!dfs_circle(i))
    121             {
    122                 printf("0
    ");
    123                 return 0;
    124             }
    125         }
    126     S=n+1;
    127     for (int i=1;i<=n;i++)
    128     {
    129         int zhi=find(i);
    130         if (!du[zhi]&&!hash[zhi])
    131         {
    132             add(S,zhi);
    133             hash[zhi]=1;
    134         }
    135     }
    136 //=========================================================================================
    137     dfs(S,-1);
    138     for (int i=1;i<=siz[S];i++)
    139         ans=(ans+f[S][i])%mod;
    140     printf("%lld
    ",ans);
    141 }
  • 相关阅读:
    SDWebImage源码解读之SDWebImageDownloader
    Swift 中函数使用指南
    SDWebImage源码解读之SDWebImageDownloaderOperation
    Swift enum(枚举)使用范例
    用C语言封装OC对象(耐心阅读,非常重要)
    终端mysql Operation not permitted错误解决方案
    SDWebImage源码解读之SDWebImageCache(下)
    SDWebImage源码解读之SDWebImageCache(上)
    SDWebImage源码解读_之SDWebImageDecoder
    递归的本质
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7705240.html
Copyright © 2011-2022 走看看