我們知道,求任意圖的最大獨立集是一類np完全問題,目前還沒有準確的多項式演算法,但是有許多多項式複雜度的近似演算法。
例如,小 c 常用的一種演算法是:
1.對於乙個 \(n\) 個點的無向圖,先等概率隨機乙個 \(1\ldots n\) 的排列 \(p[1\ldots n]\)。
2.維護答案集合 \(s\) ,一開始 \(s\) 為空集,之後按照 \(i=1\ldots n\)的順序,檢查 \(\\cup s\) 是否是乙個獨立集,如果是的話就令 \(s=\\cup s\)。
3.最後得到乙個獨立集 \(s\) 作為答案。
小 c 現在想知道,對於給定的一張圖,這個演算法的正確率,輸出答案對 \(998244353\) 取模
第一行兩個非負整數 \(n,m\) 表示給定的圖的點數和邊數。
接下來 \(m\) 行,每行有兩個正整數 \((u,v) (u\neq v)\)描述這張圖的一條無向邊。
輸出正確率,答案對 \(998244353\) 取模。
看到\(n \leq 20\) 時,有經驗的選手應該就會往狀壓dp上去想.
令\(f_\)表示當前獨立集大小為i,不能選的點集為j的方案數,\(s_u\)表示選了\(i\)後不能選的點的集合,易得
\[f_=f_+f_*a_^ u \notin j
\]複雜度 \(o(2^n * n^2)\),這看起來已經很優秀了。
繼續觀察,發現每個狀態的最大獨立集是唯一的
記\(s_j\)表示不能選的點集為j時最大的獨立集大小
每次更新\(s_j\)時將\(f_j\)清零即可
複雜度變為\(o(2^n*n)\)
#include#include#includeusing namespace std;
const int mod=998244353;
int n,m,cou[1500000],state[50],num[1500000];
long long j[50],dp[1500000],r[50];
long long fpow(long long a,int k)
return ans;
}long long a(int n,int m)
int main()
j[0]=1;
for (int i=1;i<=n;i++) j[i]=j[i-1]*i%mod;
for (int i=0;i<=n;i++) r[i]=fpow(j[i],mod-2);
dp[0]=1;num[0]=0;
for (int i=0;i<(1<>(j-1)) & 1) continue;
if (num[i]+1>num[i|state[j]]) num[i|state[j]]=num[i]+1,dp[i|state[j]]=0;
if (num[i]+1==num[i|state[j]]) dp[i|state[j]]=(dp[i|state[j]]+dp[i]*a(n-cou[i]-1,cou[i|state[j]]-cou[i]-1)%mod)%mod;
} }printf("%lld\n",dp[(1
}
PKUWC2018 隨機演算法
題意 給定乙個圖 n 20 定義乙個求最大獨立集的隨機化演算法 產生乙個排列,依次加入,能加入就加入 求得到最大獨立集的概率 本質就是計數題 每個點有三種狀態 考慮過且在獨立集中,考慮過未在獨立集中,未考慮 本來在集合裡的點不能知道有哪些,而且不能加入的點的排列也不好確定。乙個好的方法是 把考慮過的...
PKUWC2018 隨機演算法
題目 思博狀壓寫不出是不是沒救了呀 首先我們直接狀壓當前最大獨立集的大小顯然是不對的,因為我們的答案還和我們考慮的順序有關 我們發現最大獨立集的個數好像不是很多,可能是 o n 級別的,於是我們考慮從這個方面入手 我們求出所有的最大獨立集,考慮求出有多少種考慮順序能夠恰好得到這個最大獨立集 設當前已...
pkuwc2018 隨機演算法
我們考慮用狀壓dp來解決這一道題 設 f i s 表示當前排列的前i位所構成的最大獨立集恰好為s的方案數 我們考慮用 f i s 推出 f i 1 s 的值 那麼我們有兩種擴充套件的方法,一種是在第 i 1 位,加入乙個數 j 滿足 s j 且 s j 為最大獨立集。這種情況,相當於在原本的最大獨立...