[HNOI2013] standard IO Gauss elimination

Main idea:

Give you an undirected graph, let you walk around in it. After you number the edge, add the weight of the edge = = probability * the label of the edge.

Ideas:

%%%ymw
Last time, Gauss elimination was very confused. I didn't understand it for a long time. Today, I found the water problem and brushed it. That is to say, the probability of each point is set, and then the equation is solved by Gauss elimination, and finally it is transformed to the edge.

Procedure:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 501
#define M 300005
using namespace std;
int n,m,last[N],cnt,x[M],y[M],d[N];
struct data{int to,next;}e[M*2];
double f[N][N],val[M];

void add(int x,int y){
    e[++cnt].to=y; e[cnt].next=last[x]; last[x]=cnt;
    e[++cnt].to=x; e[cnt].next=last[y]; last[y]=cnt;
}

void guess(int n){
    for (int i=1;i<=n;i++){
        int l=i;
        for (int j=i+1;j<=n;j++)
         if  (abs(f[j][i])>abs(f[l][i])) l=j;
        if (l!=i) 
         for (int j=1;j<=n+1;j++)
          swap(f[i][j],f[l][j]);
        double t=f[i][i];
        for (int j=1;j<=n+1;j++)
         f[i][j]/=t;
        for (int j=1;j<=n;j++)
            if (j!=i&&f[j][i]){
                t=f[j][i];
                for (int k=1;k<=n+1;k++)
                 f[j][k]-=t*f[i][k];
            }


    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++){
        scanf("%d%d",&x[i],&y[i]);
        d[x[i]]++; d[y[i]]++;
        add(x[i],y[i]);
    }
    for (int i=1;i<n;i++){
        f[i][i]=-1;
        for (int j=last[i];j;j=e[j].next){
            if (e[j].to!=n) f[i][e[j].to]=(double)1.0/d[e[j].to]; 
        }
    }
    f[1][n]=-1; 
    guess(n-1);
    for (int i=1;i<=m;i++)
      val[i]=f[x[i]][n]/d[x[i]]+f[y[i]][n]/d[y[i]];
    sort(val+1,val+m+1);
    double ans=0.0;
    for (int i=1;i<=m;i++)
     ans+=val[i]*(m-i+1);
    printf("%.3lf",ans);
}

Posted by tasairis on Fri, 01 May 2020 01:46:21 -0700