bzoj 3143: [Hnoi2013]游走

先高斯消元求出每个点期望到达次数,再到边;
再利用排序不等式贪心求解;点1一开始就期望1;
要注意点n的特殊性,它原本期望为1,但每个点不能由它转移过去,
它的期望也与其它点无关,就让它为0以方便计算;

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
using namespace std;
const int maxn=505,maxm=maxn*maxn;
typedef double db;
int g[maxn][maxn],d[maxn],n,m,s[maxm],t[maxm];
db a[maxn][maxn],p[maxn],ans[maxm],Ans=0.0;
void gauss(){
    rep(i,1,n-1){db ok=0.0;int id=i;
        rep(j,i,n-1)if(fabs(a[j][i])>ok){ok=fabs(a[j][i]);id=j;}
        if(ok==0.0)continue;
        if(id!=i)rep(j,1,n)swap(a[id][j],a[i][j]);
        for(int j=n;j>=i;j--)
        for(int k=1;k<n;k++)if(k!=i){
            a[k][j]-=a[i][j]*a[k][i]/a[i][i];
        }
    }
    rep(i,1,n-1)p[i]=a[i][n]/a[i][i];   
}
int main(){//freopen("in.in","r",stdin);
int u,v;
    scanf("%d%d",&n,&m);
    rep(i,1,m){scanf("%d%d",&s[i],&t[i]);u=s[i];v=t[i];
    g[u][v]++;g[v][u]++;d[u]++;d[v]++;}
    rep(i,1,n-1)
    rep(j,1,n-1){
        if(i==j)a[i][j]=1.0;
        else a[i][j]=-1.0*g[i][j]/d[j];
    }
    a[1][n]=1.0;
    gauss();
    rep(i,1,m){ans[i]=(p[s[i]]*1.0/d[s[i]])+(p[t[i]]*1.0/d[t[i]]);}
    sort(ans+1,ans+1+m);
    rep(i,1,m)Ans+=(m-i+1)*1.0*ans[i];
    printf("%.3lf",Ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值