题目来源: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;
}