题意:
给出一个图,每个节点都连接着前驱和后继,现在问每个节点执行的期望数。
题解:
如果这题每个节点没有回头,那么用dp解妥妥的,但是有回路这样只能用高斯消元搞。对于每个节点的期望数设为xi,那么xi的期望数等于每个前驱的期望数/出度的总和。于是可以列出多个方程高斯消元求解,不过要注意有无穷的情况,应为会产生环!!
#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<string>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int &a,int b){ if(b>a)a=b; }
void cmin(int &a,int b){ if(b<a)a=b; }
void cmax(ll &a,ll b){ if(b>a)a=b; }
void cmin(ll &a,ll b){ if(b<a)a=b; }
void add(int &a,int b,int mod){ a=(a+b)%mod; }
void add(ll &a,ll b,ll mod){ a=(a+b)%mod; }
void add(int &a,int b){ a+=b; }
void add(ll &a,ll b){ a+=b; }
const int oo=0x3f3f3f3f;
const double eps = 1e-8;
const ll MOD = 10007;
const int maxn = 105;
double maze[maxn][maxn], x[maxn];
vector<int>pre[maxn];
int d[maxn];
bool inf[maxn];
void Gauss(int n, int m){
int r, c;
for(r = 0, c = 0; r < n && c < m; r++, c++){
int id = r;
for(int i = r + 1; i < n; i++)
if(fabs(maze[i][c]) > fabs(maze[id][c]))
id = i;
if(fabs(maze[id][c]) < eps) continue;
if(id != r){
for(int j = 0; j <= m; j++)
swap(maze[id][j], maze[r][j]);
}
for(int i = 0; i < n; i++){
if(i == r) continue;
double t = fabs(maze[i][c]) / fabs(maze[r][c]);
if(maze[r][c] * maze[i][c] < eps)
t = - t;
for(int j = c; j <= m; j++)
maze[i][j] -= maze[r][j] * t;
}
}
for(int i = 0; i < n; i++)
x[i] = (fabs(maze[i][i]) < eps) ? 0.0 : (maze[i][n] / maze[i][i]);
}
void Init(int n){
for(int i = 0; i <= n; i++)
for(int j = 0; j <= n ; j++)
maze[i][j] = 0.0;
memset(inf, false, sizeof inf);
memset(d, 0, sizeof d);
for(int i = 0; i <= n; i++)
pre[i].clear();
}
int main(){
//freopen("E:\\read.txt","r",stdin);
int n, u, v, cas = 1;
while(scanf("%d", &n) != EOF){
if(n == 0) break;
Init(n);
while(scanf("%d %d", &u, &v)){
if(u == 0 && v == 0) break;
u--; v--;
d[u]++;
pre[v].push_back(u);
}
for(int i = 0; i < n; i++){
int ss = pre[i].size();
maze[i][i] = 1.0;
for(int j = 0; j < ss; j++)
maze[i][pre[i][j]] -= 1.0 / d[pre[i][j]];
if(i == 0) maze[i][n] = 1.0;
}
Gauss(n, n);
for(int i = n - 1; i >= 0; i--){
if(fabs(maze[i][i]) < eps && fabs(maze[i][n]) > eps){
inf[i] = true;
continue;
}
for(int j = i + 1; j < n ; j++)
if(fabs(maze[i][j]) > eps && inf[j]) inf[i] = true;
}
int q;
scanf("%d", &q);
printf("Case #%d:\n", cas++);
while(q--){
scanf("%d", &u);
u--;
if(inf[u]) puts("infinity");
else printf("%.3lf\n", x[u]);
}
}
return 0;
}