标签:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
#define eps 1e-10
#define N 500020
#define B 20
#define M 3000020
#define inf 0x3f3f3f3f
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define fi first
#define se second
#define mod 1000007
#define md (ll + rr >> 1)
struct state {
int a[21], cnt;
bool operator < (const state &b) const {
return cnt < b.cnt;
}
}st[N];
int f[1000007];
int tot;
double p[N];
int n;
vector<int> s[N];
int b[N];
double dp[21][700];
double g[22][22], X[22];
int tr[700][22][22];
void dfs(int k, int mx, int sum) {
if(sum == n) {
++tot;
for(int i = 1; i < k; ++i) {
st[tot].a[i] = b[i];
}
st[tot].cnt = k - 1;
return;
}
for(int i = mx; i <= n - sum; ++i) {
if(!(n - sum - i == 0 || n - sum - i >= i)) continue;
b[k] = i;
dfs(k + 1, i, sum + i);
}
}
int code(state &t) {
int ret = t.cnt;
for(int i = 1; i <= t.cnt; ++i) {
ret = 1LL * ret * 233 % mod + t.a[i];
ret %= mod;
}
return ret;
}
int merge(state t, int x, int y) {
t.a[x] += t.a[y];
swap(t.a[y], t.a[t.cnt]);
t.cnt--;
sort(t.a + 1, t.a + t.cnt + 1);
return f[code(t)];
}
int sgn(double x) {
if(fabs(x) < eps) return 0;
return x < 0? -1: 1;
}
void gauss() {
for(int i = 1; i <= n; ++i) {
int u = -1;
for(int v = i; v <= n; ++v) {
if(u == -1 || fabs(g[v][i]) > fabs(g[u][i])) u = v;
}
if(u == -1 || sgn(g[u][i]) == 0) {
puts("error");
exit(0);
}
for(int x = i; x <= n + 1; ++x) swap(g[i][x], g[u][x]);
for(int x = i + 1; x <= n; ++x) {
if(sgn(g[x][i])) {
double tmp = g[x][i] / g[i][i];
for(int k = i; k <= n + 1; ++k) {
g[x][k] -= g[i][k] * tmp;
}
}
}
}
for(int i = n; i >= 1; --i) {
X[i] = g[i][n+1];
for(int j = i + 1; j <= n; ++j) X[i] -= g[i][j] * X[j];
X[i] /= g[i][i];
}
}
void get_data() {
freopen("tt.txt", "w", stdout);
int t = 19;
printf("1\n%d\n", t);
for(int i = 1; i <= t; ++i) printf("%.3lf ", 0.5);
for(int i = 1; i <= t; ++i) {
printf("%d ", t);
for(int j = 1; j <= t; ++j) printf("%d ", j);
puts("");
}
exit(0);
}
int main() {
// get_data();
// freopen("tt.txt", "r", stdin);
int cas, kk = 0;
scanf("%d", &cas);
while(cas--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%lf", &p[i]), s[i].clear();
for(int i = 1; i <= n; ++i) {
int t, x;
scanf("%d", &t);
while(t--) {
scanf("%d", &x);
s[i].push_back(x);
}
}
tot = 0;
dfs(1, 1, 0);
sort(st + 1, st + tot + 1);
for(int i = 1; i <= tot; ++i) {
f[code(st[i])] = i;
}
for(int i = 1; i <= n; ++i) dp[i][1] = 0;
for(int i = 2; i <= tot; ++i) {
for(int x = 1; x <= st[i].cnt; ++x) {
for(int y = x + 1; y <= st[i].cnt; ++y) {
tr[i][x][y] = merge(st[i], x, y);
}
}
}
for(int i = 2; i <= tot; ++i) {
memset(g, 0, sizeof g);
for(int u = 1; u <= n; ++u) {
double right = 1;
for(int x = 1; x <= st[i].cnt; ++x) {
for(int y = x + 1; y <= st[i].cnt; ++y) {
double tmp = st[i].a[x] * st[i].a[y];
tmp = tmp / (n * (n - 1) / 2) / s[u].size() * p[u];
int id = tr[i][x][y];
for(int zz = 0; zz < s[u].size(); ++zz) {
int z = s[u][zz];
right += dp[z][id] * tmp;
// if(st[id].cnt == 1) right -= tmp;
}
}
}
g[u][n+1] = right;
g[u][u] = 1;
double tmp = 0;
for(int x = 1; x <= st[i].cnt; ++x) tmp += st[i].a[x] * (st[i].a[x] - 1) / 2;
tmp = tmp * p[u] / (n * (n - 1) / 2) / s[u].size();
for(int x = 0; x < s[u].size(); ++x) {
int v = s[u][x];
g[u][v] -= tmp;
}
tmp = (1 - p[u]) / s[u].size();
for(int x = 0; x < s[u].size(); ++x) {
int v = s[u][x];
g[u][v] -= tmp;
}
}
gauss();
for(int j = 1; j <= n; ++j) dp[j][i] = X[j];
}
printf("Case #%d: %.6f\n", ++kk, dp[1][tot]);
}
return 0;
}hdu 4936 Rainbow Island (状压dp+高斯消元)
标签:
原文地址:http://blog.csdn.net/u013654696/article/details/51332057