UVa 10828 - Back to Kernighan-Ritchie (概率DP 期望 高斯消元)

UVA - 10828
Time Limit: 3000MSMemory Limit: Unknown64bit IO Format: %lld & %llu

[Submit]   [Go Back]   [Status]  

Description

Download as PDF

Problem I
Back to Kernighan-Ritchie
Input: 
Standard Input

Output: Standard Output

 

You must have heard the name of Kernighan and Ritchie, the authors of The C Programming Language. While coding in C, we use different control statements and loops, such as, if-then-elsefordo-while, etc. Consider the following fragment of pseudo code:

 

 

   //execution starts here

   do {

      U;

      V;

   } while(condition);

   W;

 

 

 

 

In the above code, there is a bias in each conditional branch. Such codes can be represented by control flow graphs like below:

Let the probability of jumping from one node of the graph to any of its adjacent nodes be equal. So, in the above code fragment, the expected number of times U executes is 2. In this problem, you will be given with such a control flow graph and find the expected number of times a node is visited starting from a specific node.

 

Input

Input consists of several test cases. There will be maximum 100 test cases. Each case starts with an integer: n (n ≤ 100). Here n is the number of nodes in the graph. Each node in the graph is labeled with 1 ton and execution always starts from 1. Each of the next few lines has two integers: start and end which means execution may jump from node start to node end. A value of zero for start ends this list. After this, there will be an integer q (q ≤ 100) denoting the number of queries to come. Next q lines contain a node number for which you have to evaluate the expected number of times the node is visited. The last test case has value of zero for n which should not be processed.

 

Output

Output for each test case should start with “Case #i:” with next q lines containing the results of the queries in the input with three decimal places. There can be situations where a node will be visited forever (for example, an infinite for loop). In such cases, you should print “infinity” (without the quotes). See the sample output section for details of formatting.

 

Sample Input                                  Output for Sample Input

3

1 2

2 3

2 1

0 0

3

1

2

3

3

1 2

2 3

3 1

0 0

3

3

2

1

0

Case #1:

2.000

2.000

1.000

Case #2:

infinity

infinity

infinity


Problem setter: Mohammad Sajjad Hossain

Special Thanks: Shahriar Manzoor 

 

Source


Root :: Prominent Problemsetters ::  Mohammad Sajjad Hossain
Root :: AOAPC I: Beginning Algorithm Contests -- Training Guide (Rujia Liu) :: Chapter 2. Mathematics :: Matrix & System of Linear Equations ::  Examples

[Submit]   [Go Back]   [Status]  




题意:

给出一个类似如图的程序控制图,从每个节点出发到每个后继节点的概率相等。当执行完一个没有后继的节点后,程序终止。程序总是从编号为1的节点开始执行,你的任务是对若干个查询节点,求出每个节点的期望执行次数。


马尔可夫过程

设xi表示i点期望执行次数 di表示i的出度

列出方程

xi = ∑ xj/dj,j为i的前驱节点。

因为是存在环的图,xi有可能会用到xi本身,所以需要用高斯消元来求。

移项可得:

xi - xj1/dj1 - xj2/dj2 - xj3/dj3 - .. = 0    xjk为i的前驱节点


对于1节点,因为从他开始执行,可以看为有一个虚拟节点以1的概率到达1节点,所以节点1的方程:

x1 = 1 +  ∑ xj/dj,j为1的前驱节点。移项可得

x1 - xj1/dj1 - xj2/dj2 - xj3/dj3 - .. = 1




#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 100 + 20;
vector<int> prev[maxn];
int son[maxn];

typedef double Matrix[maxn][maxn];


void gaussJordan(Matrix A, int n) {
    for(int i=0; i<n; i++) {
        int r = i;
        for(int j=i+1; j<n; j++) if(fabs(A[j][i]) > fabs(A[r][i]))
            r = j;
        if(fabs(A[r][i]) < eps) continue;
        if(r != i) for(int j=0; j<=n; j++) swap(A[r][j], A[i][j]);
        for(int k=0; k<n; k++) if(k != i) {
            for(int j=n; j>=i; j--) A[k][j] -= A[k][i] / A[i][i] * A[i][j];
        }
    }
}

Matrix A;
int inf[maxn];

int main() {
    int n;
    int kase = 1;

    while(scanf("%d", &n) != EOF && n) {
        int a, b;
        for(int i=0; i<n; i++) prev[i].clear();
        memset(son, 0, sizeof(son));
        while(scanf("%d%d", &a, &b) == 2 && (a || b)) {
            a--, b--;
            prev[b].push_back(a);
            son[a]++;
        }
        memset(A, 0, sizeof(A));
        for(int i=0; i<n; i++) {
            A[i][i] = 1;
            int sz = prev[i].size();
            for(int j=0; j<sz; j++) {
                int v = prev[i][j];
                A[i][v] -= 1.0 / son[v];
            }
        }
        A[0][n] = 1;
        gaussJordan(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", kase++);
        while(Q--) {
            int u;
            scanf("%d", &u); u--;
            if(inf[u]) puts("infinity");
            else printf("%.3lf\n", fabs(A[u][u]) < eps ? 0 : A[u][n] / A[u][u]);
        }
    }

    return 0;
}







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值