题意:
给出一个图,每个节点都连接着前驱和后继,现在问每个节点执行的期望数。
题解:
如果这题每个节点没有回头,那么用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; }