[HNOI 2013] 游走

91 篇文章 1 订阅
11 篇文章 0 订阅

题目描述:

有m条边 每条边的代价是经过这条边的次数概率*编号
从1开始到n结束
安排编号,求最小总代价

题目分析:

首先贪心,我们对概率小的边安排大的编号肯定能使的总代价最小…
直接求边的概率不好求,我们从两个点的概率推出这条边的概率
Pe=Pu/du+Pv/dv P e = P u / d u + P v / d v
怎么推点的概率啊…
Pi=Px/dx P i = ∑ P x / d x
我们从1出发,那么1的期望本来就有1,而到n结束,那么n对于概率没有贡献,设为0
这样解个n元线性方程组就好了…
别问我为啥n^3可以过500,貌似是高消常数是1/6的关系…

题目链接:

BZOJ 3143
Luogu 3232

Ac 代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <cmath> 
const int maxm=501;
int U[maxm*maxm],V[maxm*maxm];
double a[maxm][maxm],d[maxm],w[maxm*maxm];
int n,m;
inline void Gauss()
{
    for(int i=1;i<=n;i++)
    {
        int r=i;
        for(int j=i+1;j<=n;j++) if(std::fabs(a[j][i])>std::fabs(a[r][i])) r=j;
        if(r!=i) for(int j=1;j<=n+1;j++) std::swap(a[i][j],a[r][j]);
        double t=a[i][i];
        for(int j=i+1;j<=n+1;j++) a[i][j]/=t;
        for(int j=1;j<=n;j++)
        if(i!=j)
        {
            double t=a[j][i];
            for(int k=i+1;k<=n+1;k++) a[j][k]-=a[i][k]*t;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&U[i],&V[i]);
        d[U[i]]++,d[V[i]]++;    
    }
    for(int i=1;i<=n;i++) a[i][i]=-1;
    a[1][n+1]=-1.0;
    for(int i=1;i<=m;i++)
    {
        a[U[i]][V[i]]+=1/d[V[i]];
        a[V[i]][U[i]]+=1/d[U[i]];
    }
    for(int i=1;i<n;i++) a[n][i]=0;
    Gauss();
    for(int i=1;i<=m;i++)
     w[i]=a[U[i]][n+1]/d[U[i]]+a[V[i]][n+1]/d[V[i]];
    std::sort(w+1,w+m+1);
    double ans=0;
    for(int i=1;i<=m;i++)
    {
        //printf("%.3lf\n",w[i]);
        ans+=w[i]*(m-i+1);
    }
    printf("%.3lf\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值