zoukankan      html  css  js  c++  java
  • uvalive 5731 Qin Shi Huang’s National Road System

    题意:

    秦始皇要修路使得所有的城市连起来,并且花费最少;有一个人,叫徐福,他可以修一条魔法路,不花费任何的钱与劳动力。

    秦始皇想让修路的费用最少,但是徐福想要受益的人最多,所以他们经过协商,决定让 A / B 最大,A代表被魔法路连接的两个城市的人口总数,B代表修的路中非魔法路的总长度。

    输出 A / B 的最大值。

    思路:

    A / B 最大,则A尽可能大,B尽可能小,所以首先把MST求出来。由于每个城市的人口有很大的偏差,所以必须枚举每一条边,计算连接的两个城市的人口,复杂度为O(n^2),所以每次替换边的复杂度必须是O(1)。

    由于是稠密图,所以用prim算法,prim算法在O(n^2)的复杂度的时候,可以维护最小生成树上两点之间的最长边,这样就可以在过程中把两点间的最长边保存下来。这个是依靠已知的前驱节点实现的。复杂度为O(n^2)。

    枚举每一条边时,如果这条边是MST中的边,那么就直接计算 A / B;如果这条边不在MST中,加入这条边就会成环,这时我们保存的信息就起作用了,成环之后把在MST中的连接这两点的最长边去掉,就是新的生成树的权值,且保证了B尽可能小。替换的时间复杂度为O(1)。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <vector>
      5 #include <math.h>
      6 using namespace std;
      7 const int maxn = 1005;
      8 double path[maxn][maxn];
      9 double g[maxn][maxn];
     10 double dis[maxn];
     11 bool vis[maxn];
     12 bool used[maxn][maxn];
     13 int peo[maxn];
     14 int pre[maxn];
     15 double ans;
     16 struct point
     17 {
     18     int x,y;
     19 }p[maxn];
     20 
     21 double cal(int i,int j)
     22 {
     23     double x2 = (p[i].x - p[j].x) * (p[i].x - p[j].x);
     24     double y2 = (p[i].y - p[j].y) * (p[i].y - p[j].y);
     25     
     26     return sqrt(x2 + y2);
     27 }
     28 
     29 int prim(int n)
     30 {
     31     memset(vis,0,sizeof(vis));
     32     memset(path,0,sizeof(path));
     33     memset(used,0,sizeof(used));
     34     for (int i = 0;i <= n;i++) dis[i] = 1e15;
     35     
     36     vis[1] = 1;
     37     dis[1] = 0;
     38     
     39     int tot = 0;
     40     ans = 0;
     41     //double len = 0;
     42     
     43     for (int i = 2;i <= n;i++)
     44     {
     45         pre[i] = 1;
     46         dis[i] = g[1][i];
     47     }
     48     
     49     for (int i = 1;i < n;i++)
     50     {
     51         int u;
     52         double d = 1e15;
     53         
     54         for (int j = 1;j <= n;j++)
     55         {
     56             if (!vis[j] && dis[j] < d)
     57             {
     58                 d = dis[j];
     59                 u = j;
     60             }
     61         }
     62         
     63         vis[u] = 1;
     64         
     65         ans += d;
     66         
     67         //tot = max(peo[u] + peo[pre[u]],tot);
     68         
     69         used[u][pre[u]] = used[pre[u]][u] = 1;
     70         
     71         for (int j = 1;j <= n;j++)
     72         {
     73             if (vis[j] && j != u)
     74                 path[u][j] = path[j][u] = max(d,path[j][pre[u]]);
     75         }
     76         
     77         for (int j = 1;j <= n;j++)
     78         {
     79             if (!vis[j])
     80             {
     81                 if (g[u][j] < dis[j])
     82                 {
     83                     dis[j] = g[u][j];
     84                     pre[j] = u;
     85                 }
     86             }
     87         }
     88     }
     89     
     90     //printf("%.2f **
    ",ans);
     91     
     92     return tot;
     93 }
     94 
     95 int main()
     96 {
     97     int t;
     98     
     99     scanf("%d",&t);
    100     
    101     while (t--)
    102     {
    103         int n;
    104         
    105         scanf("%d",&n);
    106         
    107         for (int i = 1;i <= n;i++)
    108         {
    109             scanf("%d%d%d",&p[i].x,&p[i].y,&peo[i]);
    110         }
    111         
    112         for (int i = 1;i <= n;i++)
    113         {
    114             for (int j = 1;j <= n;j++)
    115             {
    116                 g[i][j] = 1e15;
    117             }
    118         }
    119         
    120         for (int i = 1;i <= n;i++)
    121         {
    122             for (int j = i+1;j <= n;j++)
    123             {
    124                 g[i][j] = g[j][i] = cal(i,j);
    125             }
    126         }
    127         
    128         prim(n);
    129         
    130         double ans1 = 0;
    131         
    132         for (int i = 1;i <= n;i++)
    133         {
    134             for (int j = i + 1;j <= n;j++)
    135             {
    136                 if (used[i][j])
    137                 {
    138                     int peop = peo[i] + peo[j];
    139                     ans1 = max(peop / (ans - g[i][j]),ans1);
    140                     
    141                     //printf("%d %d %d %.2f **
    ",i,j,peop,ans - g[i][j]);
    142                 }
    143                 else
    144                 {
    145                     int peop = peo[i] + peo[j];
    146                     ans1 = max(peop / (ans - path[i][j]),ans1);
    147                     //printf("%d %d %d %.2f **
    ",i,j,peop,ans - path[i][j]);
    148                 }
    149             }
    150         }
    151         
    152         printf("%.2f
    ",ans1);
    153         
    154         //printf("%.2f",path[1][4]);
    155     }
    156     
    157     return 0;
    158 }
  • 相关阅读:
    swoole 安装方法 使用即时聊天
    git的介绍以及简单应用
    curl的应用
    linux下监听和同步代码配置
    mac skim 修改背景色
    php 编译安装的一个 configure 配置
    mac mysql error You must reset your password using ALTER USER statement before executing this statement.
    yii2 控制器里 action 大小写组合造成的路由问题
    warning : json_decode(): option JSON_BIGINT_AS_STRING not implemented in xxx
    redis 自启动脚本
  • 原文地址:https://www.cnblogs.com/kickit/p/8809028.html
Copyright © 2011-2022 走看看