[Walk] HNOI2013

Face questions

https://www.luogu.org/problem/P3232

answer

On a random walk model I was impressed by the well-known map, then write the time did not understand why, now re-fill it.

First of all, a greedy. Find out the number of times after each side of expectations, then row a sequence, to the number backwards, so that to achieve "a minimum total score of expectations."

Seeking every edge $ (u, v) $ after a desired number of times, divided into $ u \ to v $ and $ v \ to u $, $ p_u $ set number of times after expectations of $ u $, $ p (u, v) = \ frac {p_u} {d_u} + \ frac {p_v} {d_v} $.

After the number of points required for each of expectations, or an adjacency matrix $ M $ (and other issues like construction law). Column vector $ P $ multiplied by this matrix.

设$sum=\sum_{i=0}^{INF}{PM^i}$

Column vector $ sum $ last $ n $ is pointless, but $ [1..n-1] $ is meaningful, is to represent the number of times after this point expectations.

Because $ P [1..n] $ $ n-1 $ before the last bit will tend to $ 0 $, $ SUM so $ $ n-1 $ before the last bit will tend to a given value, we must use the Gaussian Elimination $ O (n ^ 3) $ obtained it.

Because the $ sum $ is a geometric sequence and form, so we can use our great God of geometric series summation formula obtained $ sum $ (required matrix inversion), so that the complexity on the right.

Wait, let me look at the code no inverse matrix ah. Why do you come out of it?

Do not think the $ (MI) over $ addition, thinking about the $ (MI) $ as a multi-linear equation coefficients, the $ PM ^ {INF} -P $ as the value of the right side of this equation, then Gaussian elimination, is the value obtained in the $ $ SUM.

I want to come out this super excited ah, trained, trained, trained.

#include<cstdio>
#include<iostream>
#include<vector>
#include<cmath>
#include<cstring>
#include<algorithm>
#define ri register int
#define N 505
#define double long double
#define M 130000
#define INF 1000000007
using namespace std;

int n,m;
vector<int> to[N];
double d[N];
double mat[N][N],p[N],ans=0;
int a[M],b[M],id[M];

bool cmp(int x,int y) {
  return p[a[x]]/d[a[x]]+p[b[x]]/d[b[x]]<p[a[y]]/d[a[y]]+p[b[y]]/d[b[y]];
}

void guess() {
  for (ri i=1;i<=n;i++) {
    int p=-1; double maxa=0;
    for (ri j=i;j<=n;j++) if (fabs(mat[j][i])>maxa) maxa=fabs(mat[j][i]),p=j;
    for (ri j=1;j<=n+1;j++) swap(mat[i][j],mat[p][j]);
    for (ri j=i+1;j<=n;j++) {
      double dv=mat[j][i]/mat[i][i];
      for (ri k=1;k<=n+1;k++) mat[j][k]-=mat[i][k]*dv;
    }
  }
  p[n]=mat[n][n+1]/mat[n][n];
  for (ri i=n-1;i>=1;i--) {
    for (ri j=i+1;j<=n;j++) mat[i][n+1]-=p[j]*mat[i][j];
    p[i]=mat[i][n+1]/mat[i][i];
  }
}

int main(){
  scanf("%d %d",&n,&m);
  for (ri i=1;i<=m;i++) {
    scanf("%d %d",&a[i],&b[i]);
    to[a[i]].push_back(b[i]); to[b[i]].push_back(a[i]);
  }
  for (ri i=1;i<=n;i++) d[i]=to[i].size();
  d[n]=INF;
  for (ri i=1;i<=n-1;i++) {
    for (ri j=0;j<to[i].size();j++) {
      int x=to[i][j];
      if (x!=n) mat[i][x]=1.0/d[x];
    }
    mat[i][i]=-1.0;
  }
  mat[1][n]=-1.0;
  p[n]=0; n--;
  guess();
  for (ri i=1;i<=m;i++) id[i]=i;
  sort(id+1,id+m+1,cmp);
  ans=0;
  for (ri i=1;i<=m;i++) ans+=(p[a[id[i]]]/d[a[id[i]]]+p[b[id[i]]]/d[b[id[i]]])*(double)(m-i+1);
  printf("%.3Lf",years); 
}

Guess you like

Origin www.cnblogs.com/shxnb666/p/11426032.html