UVA - 10828 Back to Kernighan-Ritchie (方程消元)

Youmust have heard the name of Kernighan and Ritchie, the authors ofThe C Programming Language. While coding in
C, we use differentcontrol 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;

Inthe above code, there is a bias in each conditional branch. Such codes can berepresented by control flow graphs like below:

Letthe probability of jumping from one node of the graph to any of its adjacentnodes be equal. So, in the abovecode fragment, the expected number of times U executes is 2. Inthis problem, you will be given with such a control flow graph and find theexpected
number of times a node is visited starting from a specific node.

Input

Inputconsists of several test cases. There will be maximum 100 test cases. Each case starts with an integer: n (n ≤ 100).Here nis 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 twointegers: startand endwhich means execution may jump from node start to node end. A value of zero for start endsthis list. After this, there will be an integer q (q ≤ 100) denoting the numberof queries to come. Next q lines contain a
node number for which you have to evaluate theexpected number of times the node is visited. The last test case has value ofzero for nwhich should not be processed.

Output

Output for each test caseshould start with “Case #i:”with next q lines containing the results of the queries in the input with threedecimal places. There can be situations where a node will be visited forever(for example, an infinite forloop). In such cases,
you should print “infinity” (without the quotes). See thesample 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

题意:从每个结点出发到每个后继结点的概率均相等,当执行完一个没有后继结点后,整个过程停止,程序从编号为1的结点开始执行,你的任务是对于若干个查询点,求出每个结点的期望执行次数

思路:对于这道题目我们可以转换成方程:xi = xa/da + xb/db + xc/dc+...,设i的出度为di,期望执行的次数为xi,xa等是它的前驱。但是这道题目又与其他的解方程题目不一样,就是可以会有无穷大的矛盾方程或者出现多余方程,所以我们需要用高斯—约当消元法来省略回代过程,同时还要处理无穷解的可能

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const int maxn = 110;
const double eps = 1e-8;
typedef double Matrix[maxn][maxn];

Matrix A;
int n, d[maxn];
vector<int> prev[maxn];
int inf[maxn];

void gauss_jordan(Matrix A, int n) {
	int i, j, k, r;
	for (i = 0; i < n; i++) {
		r = i;
		for (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 (j = 0; j <= n; j++)
				swap(A[r][j], A[i][j]);

		for (k = 0; k < n; k++)
			if (i != k)
				for (j = n; j >= i; j--)
					A[k][j] -= A[k][i] / A[i][i] * A[i][j];
	}
}

int main() {
	int cas = 1;
	while (scanf("%d", &n) != EOF && n) {
		memset(d, 0, sizeof(d));
		for (int i = 0; i < n; i++)
			prev[i].clear();

		int a, b;
		while (scanf("%d%d", &a, &b) != EOF && a) {
			a--, b--;
			d[a]++;
			prev[b].push_back(a);
		}

		memset(A, 0, sizeof(A));
		for (int i = 0; i < n; i++) {
			A[i][i] = 1;
			for (int j = 0; j < prev[i].size(); j++)
				A[i][prev[i][j]] -= 1.0 / d[prev[i][j]];
			if (i == 0)
				A[i][n] = 1;
		}

		gauss_jordan(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, u;
		scanf("%d", &q);
		printf("Case #%d:\n", cas++);
		while (q--) {
			scanf("%d", &u);
			u--;
			if (inf[u])
				printf("infinity\n");
			else printf("%.3lf\n", fabs(A[u][u]) < eps ? 0.0 : A[u][n] / A[u][u]);
		}
	}
	return 0;
}
时间: 2024-10-14 16:56:07

UVA - 10828 Back to Kernighan-Ritchie (方程消元)的相关文章

UVA 10828 - Back to Kernighan-Ritchie(概率+高斯消元)

UVA 10828 - Back to Kernighan-Ritchie 题目链接 题意:给图一个流程图,有结点的流程,每次进入下一个流程概率是均等的,有q次询问,求出每次询问结点的执行期望 思路:高斯消元,每个结点的期望等于所有前趋结点的期望/出度的和,由于存在无限循环的情况,不能直接递推,利用高斯消元去做,判断无解的情况既为无限循环,注意如果一个式自xi为0,但是xn也为0,xi值应该是0,表示无法到达 代码: #include <cstdio> #include <cstring

uva 10808 - Rational Resistors(基尔霍夫定律+高斯消元)

题目链接:uva 10808 - Rational Resistors 题目大意:给出一个博阿含n个节点,m条导线的电阻网络,求节点a和b之间的等效电阻. 解题思路:基尔霍夫定律,任何一点的电流向量为0.就是说有多少电流流入该节点,就有多少电流流出. 对于每次询问的两点间等效电阻,先判断说两点是否联通,不连通的话绝逼是1/0(无穷大).联通的话,将同一个联通分量上的节点都扣出来,假设电势作为变元,然后根据基尔霍夫定律列出方程,因为对于每个节点的电流向量为0,所以每个节点都有一个方程,所有与该节点

uva 1560 - Extended Lights Out(枚举 | 高斯消元)

题目链接:uva 1560 - Extended Lights Out 题目大意:给定一个5?6的矩阵,每个位置上有一个灯和开关,初始矩阵表示灯的亮暗情况,如果按了这个位置的开关,将会导致周围包括自己位置的灯状态变换,求一个按开关位置,保证所有灯都灭掉. 解题思路: 枚举,枚举第一行的状态,然后递推出后面四行的状态. 高斯消元,对于每个位置对定变量,这样列出30个方程求解. C++ 枚举 #include <cstdio> #include <cstring> #include &

UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP

题目来源:UVa 10828 Back to Kernighan-Ritchie 题意:从1开始 每次等概率从一个点到和他相邻的点 有向 走到不能走停止 求停止时每个点的期望 思路:写出方程消元 方程有唯一解 多解 无解的情况 有环 一直再环里无法停止算无穷大 从1不能到的点期望为0 #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <

uva 10828 高斯消元求数学期望

Back to Kernighan-RitchieInput: 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-the

UVA 10828 Back to Kernighan-Ritchie(高斯消元)

高斯消元求概率 对于非起点,期望x[i] = ∑x[j] / deg[j] #include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<vector> #includ

UVA 1397 - The Teacher&#39;s Side of Math(高斯消元)

UVA 1397 - The Teacher's Side of Math 题目链接 题意:给定一个x=a1/m+b1/n,求原方程组 思路:由于m*n最多20,所有最高项只有20,然后可以把每个此项拆分,之后得到n种不同无理数,每一项为0,就可以设系数为变元,构造方程进行高斯消元 一开始用longlong爆了,换成分数写法也爆了,又不想改高精度,最后是机智的用了double型过的,不过用double精度问题,所以高斯消元的姿势要正确,并且最后输出要注意-0的情况 代码: #include <c

uva 1564 - Widget Factory(高斯消元+逆元)

题目链接:uva 1564 - Widget Factory 题目大意:n种零件,m次工作日程,零件序号从1到n,给出m次工作日程的信息,x,s,e,表示生产了x个零件,从星期s开始到星期e(有可能是多个星期),然后给出生产的x个零件的序号.求每个零件被生产需要多少天(保证在3到10天) 解题思路:因为不能确定每个工作日程具体生产了几天,所以对应列出的方程均为线性模方程(模7),所以在高斯消元的过程中遇到除法要转换成乘上逆元. #include <cstdio> #include <cs

UVA 1563 - SETI (高斯消元+逆元)

UVA 1563 - SETI 题目链接 题意:依据题目那个式子.构造一个序列,能生成对应字符串 思路:依据式子能构造出n个方程.一共解n个未知量,利用高斯消元去解,中间过程有取摸过程.所以遇到除法的时候要使用逆元去搞 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 105; int pow_mod(int x, int k,