首页 > 代码库 > BZOJ 3143 游走

BZOJ 3143 游走

ans=Σf[e]*w[e],其中f[e]表示e期望经过的次数。

卡精度差评。差评。差评。

但是高消写法得改改了。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxv 1050
#define maxe 1000050
#define eps 1e-10
using namespace std;
int n,m,x[maxe],y[maxe],g[maxv],nume=1,d[maxv];
double a[maxv][maxv],f[maxv],gr[maxe],ans=0;
struct edge
{
    int v,nxt;
}e[maxe];
void addedge(int u,int v)
{
    e[++nume].v=v;e[nume].nxt=g[u];
    g[u]=nume;
}
void modify(int x)
{
    double st=-1.0;int id=x;
    for (int i=x;i<=n-1;i++)
    {
        if (fabs(a[i][x])+eps>st)
        {
            st=fabs(a[i][x]);
            id=i;
        }
    }
    if (id!=x) for (int i=1;i<=n;i++) swap(a[x][i],a[id][i]);
}
void Gauss()
{
    for (int i=1;i<=n-1;i++)
    {
        modify(i);
        if (fabs(a[i][i]-1.0)>=eps)
        {
            double t=a[i][i];
            for (int j=1;j<=n;j++) a[i][j]/=t;
        }
        for (int j=1;j<=n-1;j++)
        {
            if (j==i) continue;
            double t=a[j][i];
            for (int k=1;k<=n;k++) a[j][k]-=t*a[i][k];
        }
    }
    for (int i=1;i<=n-1;i++) f[i]=a[i][n];
}
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]]++;
        addedge(x[i],y[i]);addedge(y[i],x[i]);
    }
    for (int i=1;i<=n-1;i++)
    {
        for (int j=g[i];j;j=e[j].nxt)
        {
            int v=e[j].v;
            if (v==n) continue;
            a[i][v]+=1.0/d[v];
        }
        a[i][i]+=-1.0;
    }
    a[1][n]+=-1.0;
    Gauss();
    for (int i=1;i<=m;i++) gr[i]=f[x[i]]/d[x[i]]+f[y[i]]/d[y[i]];
    sort(gr+1,gr+m+1);
    for (int i=1;i<=m;i++) ans+=gr[i]*(m-i+1);
    printf("%.3f\n",ans);
    return 0;
}

 

BZOJ 3143 游走