zoukankan      html  css  js  c++  java
  • P3232 [HNOI2013]游走 [高斯消元]

    游走

    题目描述见链接 .


    color{red}{正解部分}

    题目要求走过的 编号和期望最小,

    先求出 的期望值 f[i]f[i], 走过一条边 u,vu, v 的期望值即为 f[u]/du[u]+f[v]/du[v]f[u]/du[u] + f[v]/du[v], 最后将期望值大的边赋予较小的编号即可 .

    现在求 的期望值, f[i]=f[to]/du[to]f[i] = sum f[to]/du[to], 依此可以列出 NN 个方程, 高斯消元 解方程即可 .


    color{red}{实现部分}

    • NN 号点相连的 点, 边 不用计 NN 的贡献 .
    • 走到 11 的实际期望值 为解出的期望 +1+1 .
    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 505;
    const double eps = 1e-14;
    
    int N;
    int M;
    int num0;
    int du[maxn];
    int head[maxn];
    int u[maxn*maxn];
    int v[maxn*maxn];
    
    double B[maxn*maxn];
    double A[maxn][maxn];
    
    struct Edge{ int nxt, to; } edge[maxn*maxn<<1];
    
    void Add(int from, int to){
            edge[++ num0] = (Edge){ head[from], to };
            head[from] = num0; du[from] ++;
    }
    
    void Guass(){
            for(reg int i = 1; i < N; i ++){
                    int max_id = i;
                    for(reg int j = i+1; j < N; j ++)
                            if(fabs(A[j][i]) > fabs(A[max_id][i])) max_id = j;
                    std::swap(A[max_id], A[i]);
                    for(reg int j = N; j >= i; j --) A[i][j] /= A[i][i];
                    for(reg int j = i+1; j < N; j ++){
                            if(fabs(A[j][i]) < eps) continue ;
                            for(reg int k = N; k >= i; k --) A[j][k] -= A[j][i] * A[i][k];
                    }
            }
            for(reg int i = N-1; i >= 1; i --)
                    for(reg int j = i+1; j < N; j ++) A[i][N] -= A[j][N]*A[i][j];
    }
    
    int main(){
            N = read(), M = read();
            for(reg int i = 1; i <= M; i ++){
                    u[i] = read(), v[i] = read();
                    Add(u[i], v[i]), Add(v[i], u[i]);
            }
            for(reg int i = 1; i < N; i ++){
                    A[i][i] = 1;
                    for(reg int j = head[i]; j; j = edge[j].nxt){
                            int to = edge[j].to;
                            if(to == N) continue ;
                            A[i][to] = -1.0/du[to];
                    }
            }
            A[1][N] = 1;
            Guass();
            for(reg int i = 1; i <= M; i ++){
                    if(u[i] != N) B[i] += A[u[i]][N]/du[u[i]];
                    if(v[i] != N) B[i] += A[v[i]][N]/du[v[i]];
            }
            std::sort(B+1, B+M+1);
            double Ans = 0;
            for(reg int i = 1; i <= M; i ++) Ans += B[i] * (M-i+1);
            printf("%.3lf
    ", Ans);
            return 0;
    }
    
  • 相关阅读:
    再谈多线程编程(一)——线程的概念、多线程的创建、守护线程、线程状态的转化
    java创建线程的三种方式及其对比
    再谈Spring AOP
    初始化一个static的Map变量
    Spring AOP详解
    git命令汇总
    AngularJS如何修改URL中的参数
    VirtualBox安装Ubuntu搭建js环境的注意事项
    Sql server日期函数操作
    凤凰网股票接口
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822398.html
Copyright © 2011-2022 走看看