您的位置:首页 > 其它

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

2014-07-21 23:42 465 查看


UVA 10828 - Back to Kernighan-Ritchie

题目链接

题意:给图一个流程图,有结点的流程,每次进入下一个流程概率是均等的,有q次询问,求出每次询问结点的执行期望

思路:高斯消元,每个结点的期望等于所有前趋结点的期望/出度的和,由于存在无限循环的情况,不能直接递推,利用高斯消元去做,判断无解的情况既为无限循环,注意如果一个式自xi为0,但是xn也为0,xi值应该是0,表示无法到达

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;

const int N = 105;
const double eps = 1e-9;
int n, d
, inf
;
double a

;
vector<int> pre
;

void build() {
int u, v;
memset(d, 0, sizeof(d));
for (int i = 0; i < n; i++)
pre[i].clear();
while (~scanf("%d%d", &u, &v) && u) {
u--; v--; d[u]++;
pre[v].push_back(u);
}
memset(a, 0, sizeof(a));
for (int i = 0; i < n; i++) {
a[i][i] = 1;
for (int j = 0; j < pre[i].size(); j++)
a[i][pre[i][j]] = -1.0 / d[pre[i][j]];
if (i == 0) a[i]
= 1;
}
}

void gauss() {
for (int i = 0; i < n; i++) {
int k = i;
for (;k < n; k++)
if (fabs(a[k][i]) > eps) break;
if (k == n) continue;
for (int j = 0; j <= n; j++) swap(a[k][j], a[i][j]);
for (int j = 0; j < n; j++) {
if (i == j) continue;
if (fabs(a[k][i]) > eps) {
double x = a[j][i] / a[i][i];
for (int k = i; k <= n; k++)
a[j][k] -= x * a[i][k];
}
}
}
}

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

int main() {
int cas = 0;
while (~scanf("%d", &n) && n) {
build();
gauss();
get_inf();
int q, node;
scanf("%d", &q);
printf("Case #%d:\n", ++cas);
while (q--) {
scanf("%d", &node);
node--;
if (inf[node]) printf("infinity\n");
else printf("%.3lf\n", fabs(a[node][node]) < eps ? 0 : a[node]
/ a[node][node]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: