UVA - 10828
Description Problem I 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-else, for, do-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.
OutputOutput 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
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 |
题意:
给出一个类似如图的程序控制图,从每个节点出发到每个后继节点的概率相等。当执行完一个没有后继的节点后,程序终止。程序总是从编号为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;
}