zoukankan      html  css  js  c++  java
  • HNOI2013 游走

    题目链接:戳我

    对于一个点x来说,它的最终概率(p[x])(sum p[v]/du[v])。显然这个递推是搞不了了,所以我们考虑列方程。

    就是设(f[i][j])表示点j对点i的贡献概率,然后列出n个方程来高斯消元。初始时点1概率为1.(方程的解的意义?就相当于是刚开始是静止态,经过无数轮之后每个点的概率也将近不动,近似地也可以认为是静止态qwq)

    注意一下到第n个点就结束了,所以我们不算点n对它连边指向的点的贡献。

    代码如下:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #define MAXN 510
    using namespace std;
    int n,m,t,tot;
    int head[MAXN*MAXN*2],du[MAXN],id[MAXN*MAXN];
    double ans;
    double f[MAXN][MAXN],sum[MAXN],now[MAXN*MAXN];
    struct Edge{int nxt,to;}edge[MAXN*MAXN*2];
    inline void add(int from,int to)
    {
        edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;
        edge[++t].nxt=head[to],edge[t].to=from,head[to]=t;
        id[t]=id[t-1]=++tot;
    }
    inline void solve()
    {
        for(int i=1;i<=n;i++)
        {
            double cur=f[i][i];
            for(int j=i;j<=n+1;j++) f[i][j]/=cur;
            for(int j=i+1;j<=n;j++)
            {
                cur=f[j][i];
                for(int k=i;k<=n+1;k++)
                {
                    f[j][k]-=f[i][k]*cur;
                }
            }
        }
        for(int i=n;i>=1;i--)
        {
            sum[i]=f[i][n+1];
            for(int j=i+1;j<=n;j++)
                sum[i]-=sum[j]*f[i][j];
        }
    }
    inline bool cmp(double x,double y){return x>y;}
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
            du[u]++,du[v]++;
        }
        for(int i=1;i<=n;i++) f[i][i]=1.0;
        for(int i=1;i<n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int v=edge[j].to;
                f[v][i]-=1.0/du[i];
            }
        }
        f[1][n+1]=1.0;
        solve();
        for(int i=1;i<n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                now[id[j]]+=sum[i]/du[i];
            }
        }
        sort(&now[1],&now[m+1],cmp);
        for(int i=1;i<=m;i++) ans+=now[i]*i;
        printf("%.3lf
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    C# FTP上传文件时出现"应 PASV 命令的请求,服务器返回了一个与 FTP 连接地址不同的地址。"的错误
    ESP32 学习笔记
    ESP32 学习笔记
    C# 实现窗口无边框,可拖动效果
    C# 获取IP地址
    C# 实现程序开机自启动
    C# 设置程序最小化到任务栏右下角,鼠标左键单击还原,右键提示关闭程序
    C# 生成机器码
    C# 隐藏窗口标题栏、隐藏任务栏图标
    C# 测量程序运行时间
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10545054.html
Copyright © 2011-2022 走看看