BZOJ 3143: [Hnoi2013]游走

题解:

高斯消元解期望方程

每条边算贡献

用边算不好算

算f(x)表示到x点的次数

f(x)=sigma(f(y))/size+1

对于1和n特判一下

然后n个方程n个未知数

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=509;
const double eps=1e-9;
double douabs(double x){
    if(x<0)return -x;
    else return x;
}
int dcmp(double x){
    if(douabs(x)<eps)return 0;
    if(x<0)return -1;
    else return 1;
}

int n,m;
double E=0;

int deg[maxn]={0};
int rx[maxn*maxn],ry[maxn*maxn];

int cntedge=0;
int head[maxn]={0};
int to[maxn*maxn],nex[maxn*maxn];
void Addedge(int x,int y){
    nex[++cntedge]=head[x];
    to[cntedge]=y;
    head[x]=cntedge;
}

double a[maxn][maxn];
double ans[maxn];
void Guas(){
    for(int j=1;j<=n;++j){
        int maxline=j;
        for(int i=j+1;i<=n;++i){
            if(a[i][j]>a[maxline][j])maxline=i;
        }
        if(maxline!=j){
            for(int i=j;i<=n+1;++i)swap(a[j][i],a[maxline][i]);
        }
        for(int i=j+1;i<=n;++i){
            double t=a[i][j]/a[j][j];
            for(int k=j;k<=n+1;++k)a[i][k]=a[i][k]-t*a[j][k];
        }
    }

    for(int i=n;i>=1;--i){
        for(int j=i+1;j<=n;++j){
            a[i][n+1]-=ans[j]*a[i][j];
        }
        ans[i]=a[i][n+1]/a[i][i];
    }
}

priority_queue<double>q;

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        scanf("%d%d",&rx[i],&ry[i]);
        Addedge(rx[i],ry[i]);
        Addedge(ry[i],rx[i]);
        deg[rx[i]]++;deg[ry[i]]++;
    }
    
    for(int u=1;u<=n;++u){
        a[u][u]=-1;
        for(int i=head[u];i;i=nex[i]){
            int v=to[i];
            if(v==n)continue;
            a[u][v]=1.0/deg[v];
        }
    }
    a[1][n+1]=-1;
    Guas();
    
    ans[n]=0;
    for(int i=1;i<=m;++i){
        int x=rx[i];
        int y=ry[i];
        q.push(ans[x]/deg[x]+ans[y]/deg[y]);
    }
    for(int i=1;i<=m;++i){
        double x=q.top();q.pop();
        E+=x*i;
    }
    printf("%.3f\n",E);
    return 0;
}

 

posted @ 2018-03-25 23:35  ws_zzy  阅读(150)  评论(0编辑  收藏  举报