1. 程式人生 > 實用技巧 >[清華集訓2012]串珠子

[清華集訓2012]串珠子

這個模型見過好幾次了, 似乎很經典,就是一些點集形成的任意非連通圖都可以表示為一個連通塊和其它若干聯通塊。

#include <bits/stdc++.h>

const int mo = 1e9 + 7;

int g[17][17], n, lg[1<<16];
int all_[1<<16], ok_[1<<16], not_[1<<16];

int main() {
	scanf("%d", &n);
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=n; ++j)
			scanf("%d", &g[i][j]);
	lg[0] = -1;
	for (int i=1; i<(1<<n); ++i) lg[i] = lg[i>>1] + 1;
	for(int S=1; S<(1<<n); ++S) {
		all_[S] = 1;
		for(int i=1; i<=n; ++i)
			for(int j=i+1; j<=n; ++j)
				if(((S>>(i-1))&1) && ((S>>(j-1))&1))
					all_[S] = (1ll * all_[S] * (g[i][j] + 1ll)) % mo;
		int p = lg[S&(-S)];
		for(int subS=(S-1)&S; subS; subS=(subS-1)&S) if((subS>>p)&1) {
			not_[S] += (1ll * ok_[subS] * all_[S ^ subS]) % mo;
			not_[S] %= mo;
		}
		ok_[S] = all_[S] - not_[S];
		ok_[S] = (ok_[S] % mo + mo) % mo;
	}
	std::cout << ok_[(1<<n)-1];
	return 0;
}