zoukankan      html  css  js  c++  java
  • UVa 10828 Back to Kernighan-Ritchie (数学期望 + 高斯消元)

    题意:给定一个 n 个结点的有向图,然后从 1 结点出发,从每个结点向每个后继结点的概率是相同的,当走到一个没有后继结点后,那么程序终止,然后问你经过每个结点的期望是次数是多少。

    析:假设 i 结点的出度为 di,期望执行次数为 xi,对于一个有 n 个前继结点的 a1, a2, a3 ... an 的结点 i,可以列出方程 xi = xa1/da1 + xa2/da2 + .. + xan/dan,根据每个结点都可以列出一个方程,然后就有 n 个方程,其中结点 1 比较特殊,因为是由它开始的所以看作它有一个前继虚拟结点 0,而 0 只执行一次,所以有 n 个前继结点的 a1, a2, a3 ... an 的结点 1,可以列出方程 x1 = xa1/da1 + xa2/da2 + .. + xan/dan + 1,注意末尾有一个 1,然后就有 n 个方程,然后用高斯消元-约当消元法,注意的是此题可能有无穷多解,和惟一解,多解也就是说最后所以得到的增广矩阵 A[i][i] = 0 && A[i][n] != 0,这样就是无穷大的答案,再就是 A[i][i] = 0 && A[i][n] = 0,这样的话答案就是 0。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    #include <cmath>
    #include <stack>
    #include <sstream>
    #include <list>
    #include <assert.h>
    #include <bitset>
    #include <numeric>
    #define debug() puts("++++")
    #define gcd(a, b) __gcd(a, b)
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define fi first
    #define se second
    #define pb push_back
    #define sqr(x) ((x)*(x))
    #define ms(a,b) memset(a, b, sizeof a)
    #define sz size()
    #define pu push_up
    #define pd push_down
    #define cl clear()
    #define lowbit(x) -x&x
    //#define all 1,n,1
    #define FOR(i,n,x)  for(int i = (x); i < (n); ++i)
    #define freopenr freopen("in.in", "r", stdin)
    #define freopenw freopen("out.out", "w", stdout)
    using namespace std;
    
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const LL LNF = 1e17;
    const double inf = 1e20;
    const double PI = acos(-1.0);
    const double eps = 1e-8;
    const int maxn = 100 + 5;
    const int maxm = 1e6 + 2;
    const LL mod = 1000000007;
    const int dr[] = {-1, 1, 0, 0, 1, 1, -1, -1};
    const int dc[] = {0, 0, 1, -1, 1, -1, 1, -1};
    const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
    int n, m;
    const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    inline bool is_in(int r, int c) {
      return r >= 0 && r < n && c >= 0 && c < m;
    }
    
    vector<int> G[maxn];
    int d[maxn];
    bool ok[maxn];
    double A[maxn][maxn];
    
    void solve(){
      for(int i = 0; i < n; ++i){
        int r = i;
        for(int 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(int j = i; j <= n; ++j)  swap(A[r][j], A[i][j]);
        
        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];
      }
    }
    
    int main(){
      int kase = 0;
      while(scanf("%d", &n) == 1 && n){
        for(int i = 0; i < n; ++i)  G[i].cl;
        ms(d, 0);  ms(ok, 0);  ms(A, 0);  A[0][n] = 1.;
        int a, b;
        while(scanf("%d %d", &a, &b) == 2 && a+b){
          G[b-1].pb(a-1);  ++d[a-1];
        }
        for(int i = 0; i < n; ++i){
          A[i][i] = 1.;
          for(int j = 0; j < G[i].sz; ++j)
            A[i][G[i][j]] -= 1. / d[G[i][j]];
        }
        solve();
        for(int i = n-1; i >= 0; --i){
          if(fabs(A[i][i]) < eps && fabs(A[i][n]) > eps){  ok[i] = true;  continue; }
          for(int j = i+1; j < n; ++j)
            if(fabs(A[i][j]) > eps && ok[j])  ok[i] = true;
        }
        printf("Case #%d:
    ", ++kase);
        scanf("%d", &m);
        int x;
        while(m-- && scanf("%d", &x) == 1)
          if(ok[x-1])  puts("infinity");
          else if(fabs(A[x-1][x-1]) < eps)  printf("0.000
    ");
          else printf("%.3f
    ", A[x-1][n] / A[x-1][x-1]);
      }
      return 0;
    }
    

      

  • 相关阅读:
    Time Zone 【模拟时区转换】(HDU暑假2018多校第一场)
    HDU 1281 棋盘游戏 【二分图最大匹配】
    Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
    Codeforces Round #527 (Div. 3) D2. Great Vova Wall (Version 2) 【思维】
    Codeforces Round #527 (Div. 3) D1. Great Vova Wall (Version 1) 【思维】
    Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4) C. Connect Three 【模拟】
    Avito Cool Challenge 2018 E. Missing Numbers 【枚举】
    Avito Cool Challenge 2018 C. Colorful Bricks 【排列组合】
    005 如何分析问题框架
    004 如何定义和澄清问题
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/8603782.html
Copyright © 2011-2022 走看看