UVA 10828 Back to Kernighan-Ritchie 高斯约当消元

来源:互联网 发布:flux软件 编辑:程序博客网 时间:2024/04/29 02:47
#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <iostream>#include <algorithm>using namespace std;const double eps=1e-8;const int maxn=111;typedef double matrix[maxn][maxn];void gauss_jordan(matrix e,int n)//高斯约当消元,即消成对角矩阵{    int i,j,k,r;    for(i=0;i<n;i++)    {        r=i;        for(j=i+1;j<n;j++)            if(fabs(e[j][i])>fabs(e[r][i]))r=j;        //当e[i][i]为0时,如果解为0,则其他行可忽略xi;若解为无穷,则其他相关行必为无穷。所以可以直接省略处理        if(fabs(e[r][i])<eps)continue;        if(r!=i)for(j=0;j<=n;j++)swap(e[r][j],e[i][j]);//为了提高数值稳定性        for(k=0;k<n;k++)if(k!=i)            for(j=n;j>=i;j--)e[k][j]-=e[k][i]/e[i][i]*e[i][j];        /*        高斯消元,即消成上三角矩阵        for(k=i+1;k<n;k++)        {            double f=e[k][i]/e[i][i];            for(j=i;j<=n;j++)e[k][j]-=f*e[i][j];        }        */    }}matrix e;int n;int d[maxn];//各点的出度vector <int>pre[maxn];//各点的前驱结点int f[maxn];int main(){    int tt=0;    while(scanf("%d",&n)!=EOF)    {        int i,j,k,a,b,t,u;        if(n==0)            break;        memset(d,0,sizeof(d));        for(i=0;i<n;i++)            pre[i].clear();        while(scanf("%d%d",&a,&b)==2&&a&&b)        {            a--;            b--;            d[a]++;            pre[b].push_back(a);        }        memset(e,0,sizeof(e));        for(i=0;i<n;i++)        {            e[i][i]=1;            for(j=0;j<pre[i].size();j++)                e[i][pre[i][j]]-=1.0/d[pre[i][j]];            if(i==0)                e[i][n]=1;//开始结点,期望+1;        }        gauss_jordan(e,n);        memset(f,0,sizeof(f));//标记无穷变量        for(i=n-1;i>=0;i--)        {            if(fabs(e[i][i])<eps&&fabs(e[i][n])>eps){f[i]=1;continue;}            for(j=i+1;j<n;j++)                if(fabs(e[i][j])>eps&&f[j])f[i]=1;//与无穷变量相关的变量也是无穷变量        }        scanf("%d",&t);        printf("Case #%d:\n",++tt);        while(t--)        {            scanf("%d",&u);            u--;            if(f[u])printf("infinity\n");            else printf("%.3lf\n",fabs(e[u][u])<eps?0.0:e[u][n]/e[u][u]);        }    }    return 0;}/*注意点:    1.期望:设结点i的出度为di,期望执行次数为xi。对于一个有3个前驱结点a,b,c的结点i,可以列出方程xi=xa/da+xb/db+xc/dc。    2.对于开始结点结点,还要加上虚拟结点过来的期望1    3.当e[i][i]=e[i][n]=0时,xi=0;当e[i][i]=0,e[i][n]>0时,xi为正无穷。用高斯约当消元法求时。题中图可列方程组:                x1=1+1/2*x2                x2=x1                x3=1/2*x2*/

原创粉丝点击