zoukankan      html  css  js  c++  java
  • P3232 [HNOI2013]游走

    传送门

    一看题面就是高斯消元解 $dp$ 方程组,设 $f[x]$ 表示从起点到终点,经过节点 $x$ 的期望次数

    那么对于一个点 $x$,枚举所有相连的边 $(x,v)$ ,其中 $v eq n$,设节点 $v$ 的出度为 $du[v]$ ,那么有

    $f[x]=sum_{v}frac {f[v]} {du[v]}$

    然后对于 $n$ 个点都有一个方程,直接解方程组即可

    然后发现题目有点意思,问的是给边安排权值使得得到的权值期望最小,冷静分析一波,刚刚高斯消元解出来的东西肯定有用

    如果我们能确定每条边被经过的期望次数,那么直接按期望从小到大给从大到小的权值即可

    发现对于一条边,它被经过的期望次数其实和它连接的两点有关,具体地:

    设边为 $(u,v)$ ,那么它被经过的期望次数就是 $frac {f[u]} {du[u]}+frac {f[v]} {du[v]}$

    所以这题就解决了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    typedef double db;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=507,M=N*N;
    int n,m,du[N];
    int fir[N],from[M],to[M],cntt;
    inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
    db A[N][N],ans[N],p[M];
    void Gauss()
    {
        for(int i=1;i<=n;i++)
        {
            int pos=i;
            for(int j=i+1;j<=n;j++)
                if(fabs(A[j][i])>fabs(A[pos][i])) pos=j;
            swap(A[i],A[pos]);
            for(int j=i+1;j<=n;j++)
            {
                db t=A[j][i]/A[i][i];
                for(int k=i;k<=n+1;k++) A[j][k]-=t*A[i][k];
            }
        }
        for(int i=n;i>=1;i--)
        {
            for(int j=i+1;j<=n;j++) A[i][n+1]-=A[i][j]*ans[j];
            ans[i]=A[i][n+1]/A[i][i];
        }
    }
    int d[M][2];
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=m;i++)
        {
            d[i][0]=read(),d[i][1]=read();
            add(d[i][0],d[i][1]),add(d[i][1],d[i][0]);
            du[d[i][0]]++,du[d[i][1]]++;
        }
        for(int i=1;i<=n;i++) A[i][i]=1;
        for(int i=1;i<n;i++)
            for(int j=fir[i];j;j=from[j])
            {
                int &v=to[j];
                A[v][i]-=1.0/du[i];
            }
        A[1][n+1]=1; Gauss(); db sum=0;
        for(int i=1;i<=m;i++)
        {
            if(d[i][0]!=n) p[i]+=ans[d[i][0]]/du[d[i][0]];
            if(d[i][1]!=n) p[i]+=ans[d[i][1]]/du[d[i][1]];
        }
        sort(p+1,p+m+1); reverse(p+1,p+m+1);
        for(int i=1;i<=m;i++) sum+=p[i]*i;
        printf("%.3lf
    ",sum);
        return 0;
    }
  • 相关阅读:
    使用eNSP配置灵活QinQ
    使用eNSP配置端口QinQ
    python-多线程编程
    front-end plugin, generate pdf with html5 and jquery
    dotnetnuke peek. glance.
    a
    租房了,说一个奇妙的事情。
    总是容易忘记zen coding里怎么写标签text, mark一下吧
    springboot+druid连接池及监控配置
    springboot +mybatis分页插件PageHelper
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11505772.html
Copyright © 2011-2022 走看看