zoukankan      html  css  js  c++  java
  • 随机游走

    题目描述

    给定一张有 nn个点 mm条边的图,生成 1∼n1sim n的全排列,假设一个排列是 ppSS是当前最大独立集;如果 S∪pi是独立集就令 S=S∪piS=Scup {p_i} ;求这 n!n!个独立集有多少个为最大独立集,答案对 998244353取模。

    输入输出格式

    输入格式:

    第一行两个整数 n,mn,m 接下来 mm 行,每行两个整数 x,yx,y,表示 x,yx,y之间有边

    输出格式:

    一行,即总个数

    输入输出样例

    输入样例#1: 
    5 4
    1 2
    2 3
    3 4
    4 5
    输出样例#1: 
    56

    说明

    n<=20,m<=400

    暴力枚举所有排列大概是30分

    可以这样

    $f[S_1][S_2]$表示第前几个点加入独立集的状态为$S_1$,未加入为$S_2$

    复杂度大概是$O(n*4^{n})$

    但我们发现实际上第二维没什么用

    我们令一个独立集所有的相邻点为相邻点集

    那么如果要在数列中放相邻点集,那么显然无所谓放哪个,反正没有影响

    如果选了非相邻点集,那么相邻点集显然会在原来基础上扩大

    于是我们设

    $f[S][k]$表示独立集状态为S,选了k个相邻点

    $t[S]$表示S状态有多少相邻点

    那么转移分两种:

    1.选相邻点:

    $f[S][k+1]+=f[S][k]*(t[S]-k)$

    2.选独立点

    $f[S|(1<<i)][k]+=f[S][k]$

    于是复杂度就变成了$O(n^{2}*2^{n})$且常数很小

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 int f[1<<21][21],ans,n,m,vv[21],vis[21],t[1<<21],s[1<<21],pd[1<<21],o[1<<21],pw[21],num[1<<21],Mod=998244353,Max,cnt,p[1<<21];
     8 int main()
     9 {int i,j,u,v,flag,l,k;
    10   cin>>n>>m;
    11   for (i=1;i<=n;i++)
    12     pw[i]=1<<(i-1);
    13   for (i=1;i<=m;i++)
    14     {
    15       scanf("%d%d",&u,&v);
    16       s[u]|=pw[v];
    17       s[v]|=pw[u];
    18     }
    19   for (i=0;i<(1<<n);i++)
    20     {
    21       int tmp=0;
    22       pd[i]=1;
    23       for (j=1;j<=n;j++)
    24       if ((pw[j]&i)&&(s[j]&i)) pd[i]=0;
    25         if (pd[i])
    26         {
    27           tmp=0;
    28           for (j=1;j<=n;j++)
    29             if (i&pw[j])
    30               o[i]|=s[j],tmp++;
    31           num[i]=tmp;
    32           tmp=0;
    33           for (j=1;j<=n;j++)
    34             if (o[i]&pw[j])
    35               tmp++;
    36           t[i]=tmp;
    37         }
    38     }
    39   f[0][0]=1;
    40   for (i=0;i<(1<<n);i++)
    41     if (pd[i])
    42     {
    43       for (k=0;k<=t[i];k++)
    44       {
    45         for (j=1;j<=n;j++)
    46           if (!(i&(1<<j-1)))
    47             {
    48             if (!(i&p[i]))
    49             f[i|(1<<j-1)][k]=(f[i|(1<<j-1)][k]+f[i][k])%Mod;
    50             }
    51         if (k!=t[i])
    52           {
    53             f[i][k+1]+=1ll*f[i][k]*(t[i]-k)%Mod;
    54             f[i][k+1]%=Mod;
    55           }
    56       }
    57     }
    58   Max=0;ans=0;
    59   for (i=0;i<(1<<n);i++)
    60     {
    61       cnt=num[i];
    62       if (cnt>Max)
    63       {
    64         Max=cnt;
    65         ans=f[i][t[i]];
    66         ans%=Mod;
    67       }
    68       else if (cnt==Max)
    69       {
    70         ans+=f[i][t[i]];
    71         ans%=Mod;
    72       }
    73     }
    74   cout<<ans;
    75 }

    给定一张有n个点m条边的图,生成1-n的全排列,假设一个排列是p,S是当前最大独立集;如果S∪{pi}是独立集就令S=S∪{pi};求这n!

    个独立集是最大独立集的概率,答案对998244353取膜。

     

  • 相关阅读:
    Java基础五
    Java基础测试
    Java练习题
    Java基础四
    Java基础三
    Java基础二
    Java基础一
    大数据讲解
    python笔记之函数 二
    iOS UICollectionView的使用(用storyboard和xib创建)
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8606898.html
Copyright © 2011-2022 走看看