[HNOI2013]游走

一看就是高斯消元。

但没想到边的期望经过次数=点的期望 / 点的度数

官方数据有误。

我的代码在gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 下可以过。

在 gcc 4.6.3 g++ Main.cc -o Main -Wall -lm --static -DONLINE_JUDGE 下可以过 (去掉-O2)

/**
 * Problem:HNOI2013-d2p2
 * Author:Shun Yao
 * Time:2013.5.28
 * Result:Accepted
 * Memo:DP, greedy, guass
 */

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>

const long Maxn = 505;

long n, m, d[Maxn];
double a[Maxn][Maxn], w[Maxn];

class lnode {
public:
	long u, v;
	lnode() {}
	~lnode() {}
} line[Maxn * Maxn >> 1];

bool cmpa(double x, double y) {
	return x > y;
}

int main() {
	freopen("d2p2.in", "r", stdin);
	freopen("d2p2.out", "w", stdout);
	scanf("%ld%ld", &n, &m);
	memset(d, 0, sizeof d);
	for (long i = 1; i <= m; ++i) {
		scanf("%ld%ld", &line[i].u, &line[i].v);
		++d[line[i].u];
		++d[line[i].v];
	}
	for (long i = 1; i < n; ++i)
		a[i][i] = 1.0;
	a[1][0] = 1.0;
	for (long i = 1; i <= m; ++i) {
		if (line[i].u == n || line[i].v == n)
			continue;
		a[line[i].u][line[i].v] -= 1.0 / d[line[i].v];
		a[line[i].v][line[i].u] -= 1.0 / d[line[i].u];
	}
	for (long i = 1; i < n; ++i) {
		long pos;
		for (long j = i; j < n; ++j) {
			if (fabs(a[j][i]) > 1e-16) {
				pos = j;
				break;
			}
		}
		if (pos != i) {
			std::swap(a[pos][0], a[i][0]);
			for (long j = i; j < n; ++j)
				std::swap(a[pos][j], a[i][j]);
		}
		for (long j = i + 1; j < n; ++j)
			if (fabs(a[j][i]) > 1e-16) {
				double x = a[j][i] / a[i][i];
				a[j][0] -= a[i][0] * x;
				for (long k = i; k < n; ++k)
					a[j][k] -= a[i][k] * x;
			}
	}
	for (long i = n - 1; i; --i) {
		for (long j = i + 1; j < n; ++j)
			a[i][0] -= a[i][j] * a[j][0];
		a[i][0] /= a[i][i];
	}
	for (long i = 1; i <= m; ++i)
		w[i] = a[line[i].u][0] / d[line[i].u] + a[line[i].v][0] / d[line[i].v];
	std::sort(w + 1, w + m + 1, cmpa);
	double ans = 0.0;
	for (long i = 1; i <= m; ++i)
		ans += i * w[i];
	printf("%.3lf", ans);
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/hsuppr/p/3105906.html