• bzoj 3143 [Hnoi2013]游走(贪心,高斯消元,期望方程)


    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=3143

    【题意】

        给定一个无向图,从1走到n,走过一条边得到的分数为边的标号,问一个边的标号方法,使得路径上得分最少。

    【思路】

        设f[i]表示经过i点的期望次数。有:

            f[1]=1+sigma{ f[v] }

            f[u]=sigma{ f[v] }

        特别地,令f[n]=0,因为n点不会对任何连边做出贡献,于是记之为0。

        于是得到了n个线性方程组,可以用高斯消元法求解。

        对于一条边(u,v)的期望经过次数为:

            e=f[u]/du[u] + f[v]/du[v]

        du[u]为u点的度数。

        然后对每条边贪心地赋值,期望经过次数越大地赋值越小。

    【代码】

     1 #include<set>
     2 #include<cmath>
     3 #include<queue>
     4 #include<vector>
     5 #include<cstdio>
     6 #include<cstring>
     7 #include<iostream>
     8 #include<algorithm>
     9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
    10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
    11 using namespace std;
    12 
    13 typedef long long ll;
    14 const int N = 505; 
    15 const int M = N*N;
    16 
    17 ll read() {
    18     char c=getchar();
    19     ll f=1,x=0;
    20     while(!isdigit(c)) {
    21         if(c=='-') f=-1; c=getchar();
    22     }
    23     while(isdigit(c))
    24         x=x*10+c-'0',c=getchar();
    25     return x*f;
    26 }
    27 
    28 struct Edge {
    29     int v,nxt;
    30 }e[M];
    31 int en=1,front[N];
    32 void adde(int u,int v) 
    33 {
    34     e[++en]=(Edge){v,front[u]}; front[u]=en;
    35 }
    36 
    37 int n,m,du[N],flag[N][N];
    38 double ef[N],a[N][N]; int tot;
    39 
    40 void gause()
    41 {
    42     for(int i=1;i<=n;i++)
    43     {
    44         int r=i;
    45         for(int j=i+1;j<=n;j++)
    46             if(fabs(a[j][i])>fabs(a[r][i])) r=i;
    47         if(r!=i) for(int j=1;j<=n+1;j++) swap(a[i][j],a[r][j]);
    48         for(int j=n+1;j>=i;j--)
    49             for(int k=i+1;k<=n;k++)
    50                 a[k][j]-=a[k][i]/a[i][i]*a[i][j];
    51     }
    52     for(int i=n;i;i--)
    53     {
    54         for(int j=i+1;j<=n;j++)
    55             a[i][n+1]-=a[i][j]*a[j][n+1];
    56         a[i][n+1]/=a[i][i];
    57     }
    58 }
    59 
    60 int main()
    61 {
    62     n=read(),m=read();
    63     int u,v;
    64     FOR(i,1,m) 
    65     {
    66         u=read(),v=read();
    67         adde(u,v),adde(v,u);
    68         du[u]++,du[v]++;
    69     }
    70     FOR(u,1,n-1) 
    71     {
    72         if(u==1) a[u][n]=1;
    73         a[u][u]=1;
    74         trav(u,i) 
    75         {
    76             int v=e[i].v;
    77             if(v!=n) a[u][v]-=1.0/du[v];
    78         }
    79     }
    80     a[1][n]=1;
    81     n--;
    82     gause();
    83     FOR(u,1,n) 
    84     {
    85         trav(u,i) 
    86         {
    87             int v=e[i].v;
    88             if(v!=u&&!flag[u][v]) 
    89                 ef[++tot]=a[u][n+1]/du[u]+a[v][n+1]/du[v],
    90                 flag[u][v]=flag[v][u]=1;
    91         }
    92     }
    93     sort(ef+1,ef+tot+1);
    94     double ans=0.0;
    95     FOR(i,1,tot)
    96         ans+=ef[i]*(tot-i+1);
    97     printf("%.3lf
    ",ans);
    98     return 0;
    99 }
  • 相关阅读:
    【Ubuntu 笔记】翻译 32.1 Job Control
    【Class 学习笔记】 浮点数的储存,运算
    【Ubuntu学习笔记】 安装篇-锐捷、scim、root改密码
    【Ubuntu学习笔记】安装篇-网络配置遇到的问题
    MySQL增删改查
    Spring MVC详解
    SSH和SSM对比总结
    hibernate工作原理
    JavaBean与xml互转的方法详解
    spring MVC如何获取session传值到前台
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5341705.html
Copyright © 2020-2023  润新知