UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP

题目来源:UVa 10828 Back to Kernighan-Ritchie

题意:从1开始 每次等概率从一个点到和他相邻的点 有向 走到不能走停止 求停止时每个点的期望

思路:写出方程消元 方程有唯一解 多解 无解的情况 有环 一直再环里无法停止算无穷大 从1不能到的点期望为0

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int maxn = 110;
const double eps = 1e-8;
typedef double Matrix[maxn][maxn];
vector <int> G[maxn];
int d[maxn];
int inf[maxn];
void gauss_jordan(Matrix A, int n)
{
	int i, j, r, k;
	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)
		{
			if(r != i)
				for(j = 0; j <= n; j++)
					swap(A[r][j], A[i][j]);
			for(k = 0; k < n; k++)
			{
				if(k != i)
				{
					for(j = n; j >= i ; j--)
					{
						A[k][j] -= A[k][i]/A[i][i] * A[i][j];
					}
				}
			}
		}
	}
}
Matrix A;
int main()
{
	int cas = 1;
	int n;
	while(scanf("%d", &n) && n)
	{
		memset(d, 0, sizeof(d));
		for(int i = 0; i < n; i++)
			G[i].clear();
		int u, v;
		while(scanf("%d %d", &u, &v) && (u||v))
		{
			u--;
			v--;
			G[v].push_back(u);
			d[u]++;
		}
		memset(A, 0, sizeof(A));
		for(int i = 0; i < n; i++)
		{
			A[i][i] = 1;
			for(int j = 0; j < G[i].size(); j++)
				A[i][G[i][j]] -= 1.0 / d[G[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;
		scanf("%d", &q);
		printf("Case #%d:\n", cas++);
		while(q--)
		{
			int x;
			scanf("%d", &x);
			x--;
			if(inf[x])
			{
				puts("infinity");
				continue;
			}
			if(fabs(A[x][x]) < eps)
			{
				puts("0.000");
				continue;
			}
			printf("%.3lf\n", A[x][n] / A[x][x]);
		}
	}
	return 0;
}


你可能感兴趣的:(UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP)