zoukankan      html  css  js  c++  java
  • BZOJ 3162 独钓寒江雪

    题意是求一棵无根树本质不同独立集的个数

    那个所谓“极寒点”的选取就是独立集。

    结构相同就是树同构,完全相同就是树的形态和独立集都相同。

    我们先求出树的重心,就可以转化为有根树同构问题。

    令$f[u][1]$为在$u$的子树中,选取$u$的方案树,$f[u][0]$为在$u$的子树中,不选取$u$的方案数。

    得到最基本的DP方程:

    $f[u][0]=prod_{vin;son(u)}(f[v][0]+f[v][1])$

    $f[u][1]=prod_{vin;son(u)}f[v][0]$

    但是可能出现直径长为奇数的情况,需要分类讨论。

    判断树同构用哈希乱搞就好了。

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 using namespace std;
      6 #define maxn 500010
      7 #define mod 1000000007
      8 #define p1 2150527
      9 #define p2 1231231237
     10 #define LL long long
     11 inline int read()
     12 {
     13     int s=0,f=1;
     14     char ch=getchar();
     15     while(ch<'0'||ch>'9')
     16     {
     17         if(ch=='-')
     18             f=-1;
     19         ch=getchar();
     20     }
     21     while(ch>='0'&&ch<='9')
     22         s=s*10+ch-'0',ch=getchar();
     23     return s*f;
     24 }
     25 struct edge
     26 {
     27     int u,v,nex;
     28 }e[maxn<<1];
     29 int pr[maxn],cnt=1;
     30 int siz[maxn];
     31 void add(int u,int v)
     32 {
     33     e[++cnt]=(edge){u,v,pr[u]};
     34     pr[u]=cnt;
     35     e[++cnt]=(edge){v,u,pr[v]};
     36     pr[v]=cnt;
     37 }
     38 int rt[2],root;
     39 LL inv[maxn];
     40 LL haha[maxn];
     41 LL f[maxn][2];
     42 int st[maxn];
     43 bool cmp(int a,int b)
     44 {
     45     return haha[a]<haha[b];
     46 }
     47 LL C(int n,int m)
     48 {
     49     LL ans=n;
     50     for(;m>1;m--)
     51         ans=ans*(n-m+1)%mod*inv[m]%mod;
     52     return ans;
     53 }
     54 void dp(int u,int fa)
     55 {
     56     int top=0,i,j;
     57     haha[u]=20010416;
     58     for(i=pr[u];i;i=e[i].nex)
     59         if(e[i].v!=fa)
     60             dp(e[i].v,u);
     61     for(i=pr[u];i;i=e[i].nex)
     62         if(e[i].v!=fa)
     63             st[++top]=e[i].v;
     64     sort(st+1,st+top+1,cmp);
     65     f[u][0]=f[u][1]=1;
     66     for(i=1;i<=top;i=j)
     67     {
     68         for(j=i+1;j<=top;j++)
     69             if(haha[st[i]]!=haha[st[j]])
     70                 break;
     71         f[u][0]=f[u][0]*C((j-i-1+f[st[i]][0]+f[st[i]][1])%mod,j-i)%mod;
     72         f[u][1]=f[u][1]*C((j-i-1+f[st[i]][0])%mod,j-i)%mod;
     73     }
     74     for(i=1;i<=top;i++)
     75         haha[u]=haha[u]*p1+(haha[st[i]]+i)*p2;
     76 }
     77 int n;
     78 void dfs(int u,int fa)
     79 {
     80     bool flag=1;
     81     siz[u]=1;
     82     int i,v;
     83     for(i=pr[u];i;i=e[i].nex)
     84     {
     85         v=e[i].v;
     86         if(v!=fa)
     87         {
     88             dfs(v,u);
     89             if((siz[v]<<1)>n)
     90                 flag=0;
     91             siz[u]+=siz[v];
     92         }
     93     }
     94     if((siz[u]<<1)<n)
     95         flag=0;
     96     if(flag)
     97     {
     98         if(rt[0])
     99             rt[1]=u;
    100         else
    101             rt[0]=u;
    102     }
    103 }
    104 void init()
    105 {
    106     inv[0]=inv[1]=1;
    107     for(int i=2;i<=n;i++)
    108         inv[i]=(mod-mod/i*inv[mod%i]%mod)%mod;
    109 }
    110 int main()
    111 {
    112     n=read();
    113     init();
    114     int u,v;
    115     for(int i=1;i<=n-1;i++)
    116     {
    117         u=read();
    118         v=read();
    119         add(u,v);
    120     }
    121     dfs(1,0);
    122     if(rt[1])
    123     {
    124         root=n+1;
    125         for(int i=pr[rt[0]];i;i=e[i].nex)
    126             if(e[i].v==rt[1])
    127             {
    128                 e[i].v=e[i^1].v=root;
    129                 break;
    130             }
    131         add(root,rt[0]);
    132         add(root,rt[1]);
    133     }
    134     else
    135         root=rt[0];
    136     dp(root,0);
    137     if(!rt[1])
    138         printf("%lld",(f[root][0]+f[root][1])%mod);
    139     else
    140     {
    141         u=rt[0];
    142         v=rt[1];
    143         if(haha[u]==haha[v])
    144             printf("%lld",(f[u][0]*f[u][1]%mod+C(f[u][0]+1,2))%mod);
    145         else
    146             printf("%lld",(f[u][0]*f[v][0]%mod+f[u][1]*f[v][0]%mod+f[u][1]*f[v][0]%mod)%mod);
    147     }
    148 }
    BZOJ 3162
  • 相关阅读:
    接口开发总结
    python多线程的坑
    ImageMagick 安装 window10与错误总结
    中文时间转换数字时间
    postgresql数据库中~和like和ilike的区别
    pdfplumber库解析pdf格式
    网络基础-数据通信过程
    渗透测试思路总述
    网络基础-OSI七层模型
    网络基础-常用网络测试工具
  • 原文地址:https://www.cnblogs.com/radioteletscope/p/7588815.html
Copyright © 2011-2022 走看看