uva10828(高斯消元)

題意:
從每個結點出發到每個後繼結點的概率均相等;
當執行完一個沒有後繼結點後,整個過程停止;
程序從編號爲1的結點開始執行;
你的任務是對於若干個查詢點,求出每個結點的期望執行次數;


思路:
本來以爲又是一個求普通求期望的題,像之前一樣迭代求解就行了;
後來發現有無窮大的解,看了大白,發現要高斯消元;
線性代數又忘得很厲害了;代碼基本照着敲的;


#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 110;
const double eps = 1e-8;
typedef double Matrix[maxn][maxn];

Matrix A;
int n, d[maxn];
vector<int> pre[maxn];
int inf[maxn];

void gauss_jordan(Matrix A, int n) {
	int i, j, k, r;
	for (i = 0; i < n; i++) {
		r = i;
		for (j = i+1; j < n; j++)
			if (fabs(A[j][i]) > fabs(A[r][i]))
				r = j;

		if (fabs(A[r][i]) < eps)
			continue;
		if (r != i)
			for (j = 0; j <= n; j++)
				swap(A[r][j], A[i][j]);

		for (k = 0; k < n; k++)
			if (i != k)
				for (j = n; j >= i; j--)
					A[k][j] -= A[k][i] / A[i][i] * A[i][j];
	}
}

int main() {
	int cas = 1;
	while (scanf("%d", &n) != EOF && n) {
		memset(d, 0, sizeof(d));
		for (int i = 0; i < n; i++)
			pre[i].clear();

		int a, b;
		while (scanf("%d%d", &a, &b) != EOF && a) {
			a--, b--;
			d[a]++;
			pre[b].push_back(a);
		}

		memset(A, 0, sizeof(A));
		for (int i = 0; i < n; i++) {
			A[i][i] = 1;
			for (int j = 0; j < pre[i].size(); j++)
				A[i][pre[i][j]] -= 1.0 / d[pre[i][j]];
			if (i == 0)
				A[i][n] = 1;
		}

		gauss_jordan(A, n);
		memset(inf, 0, sizeof(inf));
		for (int i = n-1; i >= 0; i--) {
			if (fabs(A[i][i]) < eps && fabs(A[i][n]) > eps)
				inf[i] = 1;
			for (int j = i+1; j < n; j++)
				if (fabs(A[i][j]) > eps && inf[j])
					inf[i] = 1;
		}

		int q, u;
		scanf("%d", &q);
		printf("Case #%d:\n", cas++);
		while (q--) {
			scanf("%d", &u);
			u--;
			if (inf[u])
				printf("infinity\n");
			else printf("%.3lf\n", fabs(A[u][u]) < eps ? 0.0 : A[u][n] / A[u][u]);
		}
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章