uva 10828 Back to Kernighan-Ritchie (高斯消元解概率问题)

题意:

给出一个图,每个节点都连接着前驱和后继,现在问每个节点执行的期望数。

题解:

如果这题每个节点没有回头,那么用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;
}



你可能感兴趣的:(uva 10828 Back to Kernighan-Ritchie (高斯消元解概率问题))