随机游走

题目描述

给定一张有 nn个点 mm条边的图,生成 1∼n1\sim n的全排列,假设一个排列是 ppSS是当前最大独立集;如果 S∪pi是独立集就令 S=S∪piS=S\cup {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取膜。

 

posted @ 2018-03-20 07:48  Z-Y-Y-S  阅读(421)  评论(0编辑  收藏  举报