• 【BZOJ3143】[Hnoi2013]游走


    一个无向连通图,顶点从1编号到N,边从1编号到M。 
    小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数。当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和。 
    现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小。

    期望次数大的标号应该小

    p[e] = p[e.x] / out[e.x] + p[e.y] / out[e.y]

    剩下的和3270相同

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N = 510;
    int n, m, out[N];
    double p[N][N];
    bool map[N][N];
    const double eps = 1e-9;
    struct Q {
        int x, y;
        double w;
    }e[N * N];
    bool cmp(const Q& a, const Q& b) {
        return a.w > b.w;
    }
    void gauss(int n, double a[N][N]) {
        int i, j, k, r;
        for (i = 0; i < n; i ++) {
            r = i;
            for (j = i + 1; j < n; j ++)
                if (fabs(a[j][i]) > fabs(a[r][i])) r = j;
            if (r != i) for (j = 0; j <= n; j ++) swap(a[r][j], a[i][j]);
            for (k = i + 1; k < n; k ++) {
                long double f = a[k][i] / a[i][i];
                for (j = i; j <= n; j ++) a[k][j] -= f * a[i][j];
            }
        }
        for (i = n - 1; i >= 0; i --) {
            for (j = i + 1; j < n; j ++)
                a[i][n] -= a[j][n] * a[i][j];
            a[i][n] /= a[i][i];
        }
    }
    int main() {
        freopen("a.in", "r", stdin);
        scanf("%d%d", &n, &m);
        for (int i = 1, a, b; i <= m; i ++) {
            scanf("%d%d", &e[i].x, &e[i].y);
            e[i].x--;
            e[i].y--;
            map[e[i].x][e[i].y] = map[e[i].y][e[i].x] = true;
            out[e[i].x]++;
            out[e[i].y]++;
        }
        n --;
        for (int i = 0; i < n; i ++)
            for (int j = 0; j < n; j ++)
                if (map[i][j])
                    p[i][j] = 1.0 / out[j];
        for (int i = 0; i < n; i ++)
            p[i][i] -= 1;
        p[0][n] = -1;
        gauss(n, p);
        for (int i = 1; i <= m; i ++)
            e[i].w = p[e[i].x][n] / out[e[i].x] + p[e[i].y][n] / out[e[i].y];
        sort(e + 1, e + 1 + m, cmp);
        double ans = 0;
        for (int i = 1; i <= m; i ++)
            ans += e[i].w * i;
        printf("%.3lf
    ", ans);
        return 0;
    }
  • 相关阅读:
    如何计算两个日期之间相差天数
    解决并发问题的小技巧
    Linq实现下拉框绑定
    No DataType in DataTemplate in Windows Phone(二)
    使用TOAD操作oracle初步
    使用log4net记录server Log
    尘世一场烟火
    No DataType in DataTemplate in Windows Phone(—)
    MVC设置初始页时发生的无法找到资源的简单错误
    oracle 使用in的灵异事件
  • 原文地址:https://www.cnblogs.com/tellmewtf/p/4580759.html
Copyright © 2020-2023  润新知