1. 程式人生 > >uva-10828 期望dp+gauss

uva-10828 期望dp+gauss

傳送門

題意:給你一個有向圖,從1號節點出發,問經過某個點的期望次數。

思路:傳遞閉包寫錯wa到哭。設 dp[i]為經過i點期望

dp[v]=dp[u1]*p1+dp[u2]*p2+....(對於第一個點應該再+1)

將每個dp看做變數,就可以構成n*n的矩陣比如樣例1構成矩陣如下

-1    1  0    -1

0.5   -1   0   0

 0    0.5  -1  0

用高斯消元解就可以,對於有解得dp直接輸出就可以,對於無窮的,與他相關的點也無窮,也就是他傳遞閉包能到的點。

程式碼一:

#include<bits/stdc++.h>
using namespace std;
#define eps 1e-9
const int MAXN=110;
double a[MAXN][MAXN], x[MAXN];
int equ, var;
int n;

int gauss(){
    int i, j, k, col, max_r;
    for(k=0, col=0; k<equ&&col<var; k++, col++){
        max_r=k;
        for(i=k+1; i<equ; i++)
            if(fabs(a[i][col])>fabs(a[max_r][col]))
                max_r=i;

        if(fabs(a[max_r][col])<eps) return 0;
        if(k!=max_r){
            for(j=col; j<var; j++)
                swap(a[k][j], a[max_r][j]);
            swap(x[k], x[max_r]);
        }
        x[k]/=a[k][col];
        for(j=col+1; j<var; j++) a[k][j]/=a[k][col];
        a[k][col]=1;
        for(i=0;i<equ; i++)
        if(i!=k){
            x[i]-=x[k]*a[i][col];
            for(j=col+1; j<var; j++) a[i][j]-=a[k][j]*a[i][col];
            a[i][col]=0;
        }
    }


    return 0;
}

vector<int> G[110];
int dgr[110];
bitset<110> inf;
int mp[110][110];

int main(){
    int cas=0;

    while(~scanf("%d", &n) && n){
        memset(a, 0, sizeof a);
        memset(x, 0, sizeof x);
        memset(mp, 0, sizeof mp);
        inf.reset();

        for(int i=0; i<n; i++)
            G[i].clear(), dgr[i]=0, a[i][i]=-1;
        int u, v;
        while(scanf("%d%d", &u, &v)&&(u||v)){
            u--; v--;
            G[u].push_back(v);
            mp[u][v]=1;
            dgr[u]++;
        }
        equ=n, var=n;
        x[0]=-1;
        for(int i=0; i<n; i++){
            for(int j=0; j<G[i].size(); j++){
                int v=G[i][j];
                a[v][i]+=1./dgr[i];
            }
        }

        for(int k=0; k<n; k++)
            for(int i=0; i<n; i++)
                for(int j=0; j<n; j++)
                    if(mp[i][k] && mp[k][j]) mp[i][j]=1;

        gauss();

        for(int i=0; i<n; i++){
            if(fabs(x[i])>eps && fabs(a[i][i])<eps) inf[i]=1;
            
            if(inf[i])
            for(int j=0; j<n; j++)
                if(mp[i][j]) inf[j]=inf[i];
        }

        printf("Case #%d:\n", ++cas);
        int Q, p;
        scanf("%d", &Q);
        while(Q--){
            scanf("%d", &p);
            p--;
            if(inf[p])
                puts("infinity");
            else{
                printf("%.3lf\n", fabs(x[p]));
            }
        }

    }

    return 0;
}

程式碼二:

#include<bits/stdc++.h>
using namespace std;
#define eps 1e-9
const int MAXN=110;
double a[MAXN][MAXN], x[MAXN];
int equ, var;
int n;

int gauss(){
    int i, j, k, col, max_r;
    for(k=0, col=0; k<equ&&col<var; k++, col++){
        max_r=k;
        for(i=k+1; i<equ; i++)
            if(fabs(a[i][col])>fabs(a[max_r][col]))
                max_r=i;

        if(fabs(a[max_r][col])<eps) return 0;
        if(k!=max_r){
            for(j=col; j<var; j++)
                swap(a[k][j], a[max_r][j]);
            swap(x[k], x[max_r]);
        }
        x[k]/=a[k][col];
        for(j=col+1; j<var; j++) a[k][j]/=a[k][col];
        a[k][col]=1;
        for(i=0;i<equ; i++)
        if(i!=k){
            x[i]-=x[k]*a[i][col];
            for(j=col+1; j<var; j++) a[i][j]-=a[k][j]*a[i][col];
            a[i][col]=0;
        }
    }


    return 0;
}

vector<int> G[110];
int dgr[110];
bitset<110> inf;

int main(){
    int cas=0;
    //freopen("E:/in.txt", "r", stdin);
    //freopen("E:/example.txt", "w", stdout);
    while(~scanf("%d", &n) && n){
        memset(a, 0, sizeof a);
        memset(x, 0, sizeof x);
        inf.reset();

        for(int i=0; i<n; i++)
            G[i].clear(), dgr[i]=0, a[i][i]=-1;
        int u, v;
        while(scanf("%d%d", &u, &v)&&(u||v)){
            u--; v--;
            G[u].push_back(v);
            dgr[u]++;
        }
        equ=n, var=n;
        x[0]=-1;
        for(int i=0; i<n; i++){
            for(int j=0; j<G[i].size(); j++){
                int v=G[i][j];
                a[v][i]+=1./dgr[i];
            }
        }
        gauss();

        for(int i=n-1; i>=0; i--){
            if(fabs(x[i])>eps && fabs(a[i][i])<eps) inf[i]=1;
            for(int j=i+1; j<n; j++) if(fabs(a[i][j])>eps && inf[j]) inf[i]=1;
        }

        printf("Case #%d:\n", ++cas);
        int Q, p;
        scanf("%d", &Q);
        while(Q--){
            scanf("%d", &p);
            p--;
            if(inf[p])
                puts("infinity");
            else{
                printf("%.3lf\n", fabs(x[p]));
            }
        }

    }

    return 0;
}
/*
3
1 3
3 2
0 0
3
1
2
3

5
1 2
3 5
2 4
3 1
4 2
2 3
4 5
0 0
5
1
2
3
4
5


*/