BZOJ 3534: [Sdoi2014]重建

给每条边赋权值为 \(\frac{p}{1-p}\),用基尔霍夫矩阵求出所有生成树权值积之和,最后乘上 \(\prod 1 - p\) 即可

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
#define pii pair<int, int>
#define pli pair<ll, int>
#define SZ(x) ((int)(x).size())
#define lp p << 1
#define rp p << 1 | 1
#define mid ((l + r) / 2)
#define lowbit(i) ((i) & (-i))
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=((b)-1);i>=(a);i--)
#define Edg int ccnt=1,head[N],to[E],ne[E];void addd(int u,int v){to[++ccnt]=v;ne[ccnt]=head[u];head[u]=ccnt;}void add(int u,int v){addd(u,v);addd(v,u);}
#define Edgc int ccnt=1,head[N],to[E],ne[E],c[E];void addd(int u,int v,int w){to[++ccnt]=v;ne[ccnt]=head[u];c[ccnt]=w;head[u]=ccnt;}void add(int u,int v,int w){addd(u,v,w);addd(v,u,w);}
#define es(u,i,v) for(int i=head[u],v=to[i];i;i=ne[i],v=to[i])
const int MOD = 1000000007,INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
void M(int &x) {if (x >= MOD)x -= MOD; if (x < 0)x += MOD;}
int qp(int a, int b = MOD - 2, int mod = MOD) {int ans = 1; for (; b; a = 1LL * a * a % mod, b >>= 1)if (b & 1)ans = 1LL * ans * a % mod; return ans % mod;}
template<class T>T gcd(T a, T b) { while (b) { a %= b; std::swap(a, b); } return a; }
template<class T>bool chkmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template<class T>bool chkmax(T &a, T b) { return a < b ? a = b, 1 : 0; }

const int N = 55;
const db eps = 1e-9;
db mat[N][N];

db gauss(int n) {
	rep (i, 1, n + 1) {
		int r = i;
		rep (j, i + 1, n + 1) {
			if (std::fabs(mat[r][i]) < std::fabs(mat[j][i])) r = j;
		}
		if (r != i) {
			rep (j, 1, n + 1) {
				std::swap(mat[i][j], mat[r][j]);
			}
		} else if (std::fabs(mat[i][i]) < eps) {
			return 0;
		}
		rep (j, 1, n + 1) {
			if (j != i) {
				db t = mat[j][i] / mat[i][i];
				rep (k, i, n + 1) mat[j][k] -= mat[i][k] * t;
			}
		}
	}
	db ans = 1;
	rep (i, 1, n + 1) ans *= mat[i][i];
	return ans;
}

int n;

int main() {
#ifdef LOCAL
	freopen("ans.out", "w", stdout);
#endif
	scanf("%d", &n);
	db ans = 1;
	rep (i, 1, n + 1) {
		rep (j, 1, n + 1) {
			db x;
			scanf("%lf", &x);
			if (i == j) continue;
			if (x + eps > 1.0) x -= eps;
			if (i < j) ans *= 1 - x;
			mat[i][i] += x / (1 - x);
			mat[i][j] = -x / (1 - x);
		}
	}
	printf("%.10f\n", ans * gauss(n - 1));
#ifdef LOCAL
	printf("%.10f\n", (db)clock() / CLOCKS_PER_SEC);
#endif
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12585740.html