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 }
  • 相关阅读:
    python之Socket网络编程
    python_异常处理
    python_面向对象编程
    Vue-cli3与springboot项目整合打包
    命令打开java控制面板
    后端记录用户登录失败次数
    跨域问题解决办法
    vue-i18n多语言文件归类的两种方法
    svn全局设置过滤文件没有作用的解决办法
    vue数据变化后页面刷新
  • 原文地址:https://www.cnblogs.com/kickit/p/8809028.html
Copyright © 2011-2022 走看看