传送门
Description
我们知道,求任意图的最大独立集是一类NP完全问题,目前还没有准确的多项式算法,但是有许多多项式复杂度的近似算法。
例如,小 C 常用的一种算法是:
- 对于一个 \(n\) 个点的无向图,先等概率随机一个 $1\ldots n $的排列 \(p[1\ldots n]\)。
- 维护答案集合 \(S\),一开始 \(S\) 为空集,之后按照 \(i=1\ldots n\) 的顺序,检查 \(\{p[i]\}\cup S\) 是否是一个独立集,如果是的话就令 \(S=\{p[i]\}\cup S\)。
- 最后得到一个独立集 \(S\) 作为答案。
小 C 现在想知道,对于给定的一张图,这个算法的正确率,输出答案对 \(998244353\)取模
Solution
其实并没有很难。
\(f[S]\)表示当前排列中的元素状态为\(S\)时的准确率,\(g[S]\)表示它的最大独立集大小。
我们不妨枚举\(S\)排列的第\(1\)个数\(j\),从\(S\)中去掉包括\(j\)在内的所有与\(j\)有关联的点得到集合\(S'\),显然,若\(S\)排列的第\(1\)个数为\(j\),它的准确率就是\(f[S']\)。所以:
\[f[S]=\frac{\sum f[S']}{|S|}\]
最后答案就是\(f[U]\)啦
Code?
//2019.1.16 8:24~9:20 PaperCloud
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
#define mod 998244353
int N,f[1<<20],g[1<<20],s[20],inv[22];
int main()
{
register int n=read(),m=read(),i,j,cnt,k;
while(m--) i=read()-1,j=read()-1,s[i]|=1<<j,s[j]|=1<<i;
for(i=0;i<n;++i) s[i]|=1<<i;
for(inv[1]=f[0]=1,i=2;i<=n;++i) inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
for(N=1<<n,i=1;i<N;f[i]=1ll*f[i]*inv[cnt]%mod,++i)
for(cnt=j=0;j<n;++j)if(i>>j&1)
{
cnt++;g[i]<g[k=i&(~s[j])]+1?(g[i]=g[k]+1,f[i]=0):0;
g[i]==g[k]+1?(f[i]+=f[k])%=mod:0;
}
return 0*printf("%d\n",f[N-1]);
}
Blog来自PaperCloud,未经允许,请勿转载,TKS!
原文地址:https://www.cnblogs.com/PaperCloud/p/10275265.html
时间: 2024-11-06 09:31:54