您的位置:首页 > 其它

UVa 10828 Back to Kernighan-Ritchie (高斯-约当消元)

2016-12-21 17:24 549 查看

UVa 10828 Back to Kernighan-Ritchie

题目大意:

给出一个程序控制流图,从每个结点出发到其后继结点的概率相等.当执行完一个没有后继的结点后,程序终止.程序总是从编号为1的结点开始执行.求出多个询问结点的期望执行次数.

数据不超过100组,第一行为n(1≤n≤100),结点编号为1到n.以下若干行每行包含a,b两个整数,以a=b=0位结束表示,下一行为q,接下来是q个询问,每行一个整数,若无解,输出”infinity”.结束标志为n=0.

题目分析:

设i号结点的出度为outi,那么从i号结点到其每个后继结点的概率为1/outi.

用p表示结点的前驱结点,对于每个结点u的期望执行次数xu,则有

xu=xp1/out1+xp2/out2+...+xpk/outk

将式子右边的未知数移动到左边

xu−xp1/out1−xp2/out2−...−xpk/outk=0

对于任意一个结点都可以建立一个方程,则可以建立方程组.

当然,由于程序总是从1号点开始,所以可以理解为有一个0号结点后继结点有且仅有1号结点,且x0=1.

不过还要判断其是否有解,则若出现kxu=b,k=0&&b!=0时,xu无解.且若存在xv与xu存在于同一等式中,则xv也无解.

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;

const double eps=1e-8;//切记浮点数判断的时候要加上绝对值fabs!
const int maxn=100+5;
typedef double Matrix[maxn][maxn];

void Gauss_Jordan(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[r][i])<fabs(A[j][i])) r=i;
if(r!=i) for(int j=0;j<n;j++) swap(A[i][j],A[r][i]);
if(fabs(A[i][i])<eps) continue;//若|A[i][i]|max=0,放弃操作,作为后续判断是否有解依据
for(int j=0;j<n;j++) if(j!=i)
for(int k=n;k>=i;k--)
A[j][k]-=A[j][i]/A[i][i]*A[i][k];
}
}

Matrix A;
vector<int>pre[maxn];//pre[v]表示v点的前驱结点
int out[maxn],inf[maxn];//out[u]表示u点的出度

void init(int n)
{
memset(A,0,sizeof(A));
memset(inf,0,sizeof(inf));
memset(out,0,sizeof(out));
for(int i=0;i<n;i++) pre[i].clear();
}

int main()
{
int n,a,b,q,u,kase=0;
while(scanf("%d",&n)==1&&n) {
init(n);
while(scanf("%d%d",&a,&b)==2&&a)
pre[--b].push_back(--a),++out[a];
A[0]
=1;
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/out[pre[i][j]];
}
Gauss_Jordan(A,n);
for(int i=0;i<n;i++) {
if(A[i][i]<eps&&fabs(A[i]
)>eps) inf[i]=1;//未知数系数为0,常数项不为0,未知数无解
if(inf[i]) for(int j=0;j<n;j++)//凡是涉及到无解未知数的未知数,一样是无解
if(j!=i&&fabs(A[j][i])>eps) inf[j]=1;
}
scanf("%d",&q);
printf("Case #%d:\n",++kase);
while(q--) {
scanf("%d",&u);
if(inf[--u]) printf("infinity\n");
else printf("%.3lf\n",fabs(A[u][u])<eps?0:A[u]
/A[u][u]);
//若在有解的前提下,A[u][u]=0;说明无法从起点到达u点,所以其期望为0
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  UVa 高斯-约当消元