zoukankan      html  css  js  c++  java
  • [loj2091]小星星

    (分别用$E_{T}$和$E_{G}$表示树和图的边集)

    简单分析,可以发现题目即求排列$p_{i}$的数量,满足$forall (x,y)in E_{T},(p_{x},p_{y})in E_{G}$(记为条件$A$)

    定义$count(S)$为:序列$p_{i}$的数量(忽略排列的限制),满足条件$A$且$forall 1le ile n,p_{i}in S$

    事实上,我们的答案即求$sum_{Ssubseteq [1,n]}(-1)^{n-|S|}f(S)$

    证明可以考虑每一个满足条件$A$序列$p_{i}$的对答案的贡献:

    1.若$p_{i}$是排列,显然仅有$S=[1,n]$时有贡献,且恰好为1

    2.若$p_{i}$不为排列,令$T={a_{i}}$其贡献即$sum_{Tsubseteq Ssubseteq [1,n]}(-1)^{n-|S|}$,由于其不为排列,存在$1le xle n$且$x otin T$,任取其中的一个$x$,考虑$x$是否存在不难发现两者恰好抵消,即贡献为0

    综上,即仅有排列对答案有1的贡献,即得证

    不妨暴力枚举$S$,考虑如何求$f(S)$:对树进行dp,用$f_{i,j}$表示以$i$为根的子树内且$p_{i}=j$的方案数,枚举儿子的值转移即可,复杂度为$o(n^{3})$

    最终复杂度即$o(n^{3}2^{n})$,可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 20
     4 #define ll long long
     5 struct Edge{
     6     int nex,to;
     7 }edge[N<<1];
     8 int E,n,m,x,y,head[N],vis[N][N];
     9 ll ans,f[N][N];
    10 void add(int x,int y){
    11     edge[E].nex=head[x];
    12     edge[E].to=y;
    13     head[x]=E++;
    14 }
    15 void dfs(int k,int fa,int S){
    16     for(int i=0;i<n;i++)
    17         if (S&(1<<i))f[k][i]=1;
    18         else f[k][i]=0;
    19     for(int i=head[k];i!=-1;i=edge[i].nex)
    20         if (edge[i].to!=fa){
    21             dfs(edge[i].to,k,S);
    22             for(int j=0;j<n;j++)
    23                 if (S&(1<<j)){
    24                     ll s=0;
    25                     for(int t=0;t<n;t++)
    26                         if (vis[j][t])s+=f[edge[i].to][t];
    27                     f[k][j]*=s;
    28                 }
    29         }
    30 }
    31 int main(){
    32     scanf("%d%d",&n,&m);
    33     memset(head,-1,sizeof(head));
    34     for(int i=1;i<=m;i++){
    35         scanf("%d%d",&x,&y);
    36         x--,y--;
    37         vis[x][y]=vis[y][x]=1;
    38     }
    39     for(int i=1;i<n;i++){
    40         scanf("%d%d",&x,&y);
    41         x--,y--;
    42         add(x,y);
    43         add(y,x);
    44     }
    45     for(int i=0;i<(1<<n);i++){
    46         dfs(0,0,i);
    47         ll s=0;
    48         for(int j=0;j<n;j++)s+=f[0][j];
    49         for(int j=0;j<n;j++)
    50             if (i&(1<<j))s*=-1;
    51         ans+=s;
    52     }
    53     if (n&1)ans*=-1;
    54     printf("%lld",ans);
    55 }
    View Code
  • 相关阅读:
    【译】第33节---种子数据
    python文件的读写
    python-----实现数据库安装和连接操作
    学习进度(第三周)
    解 idea(.IntelliJIdea2019.3)双击打不开的原因
    python爬虫------处理cookie的相关请求
    安装retrying模块出现 (Retry(total=4, connect=None, read=None, redirect=None, status=None))
    java----统计疫情可视化展示--echarts(三)
    java----统计疫情可视化展示--echarts(二)
    java----统计疫情可视化展示--echarts
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14596765.html
Copyright © 2011-2022 走看看