UVA 10828

来源:互联网 发布:it绩效考核 编辑:程序博客网 时间:2024/06/06 09:20

题目链接

10828 - Back to Kernighan-Ritchie

分析

白书经典题目,每一个顶点用期望的线性性质列出方程.不过要注意特殊情况以及结合具体含义来分析,用gauss_jordan消元(转化为阶梯阵)之后.若有一行A[i][i]=0并且A[i][n]=0,则说明此点不可被访问0次.继续若有矛盾方程A[i][i] = 0而A[i][n]不等于0则说明A[i][i]无解即不可能访问到终太,达到无限大.同时若有一个无解变量在某一个方程中当前元肯定无解.

AC code

#include <cstdio>#include <iostream>#include <vector>#include <queue>#include <algorithm>#include <cmath>#include <cstring>#include <map>#include <set>#include <iomanip>#include <bitset>#define pb push_back#define mp make_pair#define PI acos(-1)#define fi first#define se second#define INF 0x3f3f3f3f#define INF64 0x3f3f3f3f3f3f3f3fusing namespace std;const int MOD = 1e9+7;const int MAX_P = 2e4+10;const int maxn = 100+10;const int MAX_V = 5e5+10;const double eps = 1e-8;typedef long long LL;typedef long double DB;typedef pair<int,int> Pair;typedef double Matrix[maxn][maxn];int n;//消元为对角阵void gauss_jordan(Matrix A,int n){    //A增广矩阵,第n列是结果列    for(int i=0 ; i<n ; ++i){        int r = i;//元素最大列        for(int j = i+1 ; j<n ; ++j)            if(abs(A[j][i]) > abs(A[r][i]))r = j;        if(abs(A[r][i]) < eps)continue;        if(r!=i)for(int j = 0 ; j<=n; ++j)swap(A[r][j],A[i][j]);//交换        //与i行以外的所有行消元,化为阶梯阵,与gauss消元的不同        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 d[maxn];//出度std::vector<int> p[maxn];//前驱int inf[maxn];//无穷记号int main() {    int kase =0;    while (scanf("%d",&n )&&n) {        int x,y;        for(int i=0 ; i<n ; ++i)p[i].clear();        memset(d,0,sizeof(d));        memset(A,0,sizeof(A));        memset(inf,0,sizeof(inf));        while (scanf("%d%d",&x,&y ) && x) {            --x,--y;            ++d[x];            p[y].pb(x);        }        //构照方程组        for(int i=0 ; i<n ; ++i){            A[i][i] = 1;            for(int j=0 ; j<p[i].size() ; ++j){                A[i][p[i][j]]=-1.0/d[p[i][j]];            }        }        A[0][n] = 1;        gauss_jordan(A,n);        for(int i=n-1 ; i>=0 ; --i){            if(abs(A[i][i]) <eps &&abs(A[i][n])>eps)inf[i] = 1;            for(int j=i+1 ; j<n ; ++j)                if(abs(A[i][j])>eps && inf[j])inf[i] =1;        }        int q;        printf("Case #%d:\n", ++kase);        scanf("%d",&q );        while (q--) {            int x;scanf("%d",&x );            --x;            if(inf[x])puts("infinity");            else printf("%.3lf\n", abs(A[x][x])<eps?0.000 : A[x][n]/A[x][x]);        }    }    return 0;}
0 0