• 「PKUWC2018」随机算法


    传送门

    Description

    我们知道,求任意图的最大独立集是一类NP完全问题,目前还没有准确的多项式算法,但是有许多多项式复杂度的近似算法。

    例如,小 C 常用的一种算法是:

    1. 对于一个 (n) 个点的无向图,先等概率随机一个 $1ldots n $的排列 (p[1ldots n])
    2. 维护答案集合 (S),一开始 (S) 为空集,之后按照 (i=1ldots n) 的顺序,检查 ({p[i]}cup S) 是否是一个独立集,如果是的话就令 (S={p[i]}cup S)
    3. 最后得到一个独立集 (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
    ",f[N-1]);
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    最权威的 Android Oreo 新特性详解
    【送书福利】第一次送书活动(总共10本)
    【资源篇】Python那么火,你还不知道如何人门?
    不忘初心,方得始终 ,让我们一起学习成长,感谢有你!
    搭建环境篇 | 运行第一个Java Web 项目
    为什么我们需要看技术公众号文章?
    手把手教学APK反编译实现源码阅读
    分享一款 Google Pixel 2 独家动态壁纸
    了解CoordinatorLayout,在项目中运用
    jdk 与 jre的区别
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10275265.html
Copyright © 2020-2023  润新知