zoukankan      html  css  js  c++  java
  • 洛谷P1265 公路修建

    P1265 公路修建

      • 177通过
      • 600提交
    • 题目提供者该用户不存在
    • 标签图论
    • 难度普及+/提高

    提交该题 讨论 题解 记录

    最新讨论

    • long long类型赋值-1为什么…
    • p党80的进
    • 为什么不过啊。。。

    题目描述

    某国有n个城市,它们互相之间没有公路相通,因此交通十分不便。为解决这一“行路难”的问题,政府决定修建公路。修建公路的任务由各城市共同完成。

    修建工程分若干轮完成。在每一轮中,每个城市选择一个与它最近的城市,申请修建通往该城市的公路。政府负责审批这些申请以决定是否同意修建。

    政府审批的规则如下:

    (1)如果两个或以上城市申请修建同一条公路,则让它们共同修建;

    (2)如果三个或以上的城市申请修建的公路成环。如下图,A申请修建公路AB,B申请修建公路BC,C申请修建公路CA。则政府将否决其中最短的一条公路的修建申请;

    (3)其他情况的申请一律同意。

    一轮修建结束后,可能会有若干城市可以通过公路直接或间接相连。这些可以互相:连通的城市即组成“城市联盟”。在下一轮修建中,每个“城市联盟”将被看作一个城市,发挥一个城市的作用。

    当所有城市被组合成一个“城市联盟”时,修建工程也就完成了。

    你的任务是根据城市的分布和前面讲到的规则,计算出将要修建的公路总长度。

    输入输出格式

    输入格式:

    第一行一个整数n,表示城市的数量。(n≤5000)

    以下n行,每行两个整数x和y,表示一个城市的坐标。(-1000000≤x,y≤1000000)

    输出格式:

    一个实数,四舍五入保留两位小数,表示公路总长。(保证有惟一解)

    输入输出样例

    输入样例#1:
    4
    0 0
    1 2
    -1 2
    0 4
    输出样例#1:
    6.47

    说明

    修建的公路如图所示:

    分析:可以证明第二个规则是不存在的,因为每个城市只会选择最近的城市修路,所以不可能构成环,如果没有第二个规则,那么完完全全就是一个最小生成树,但是发现数据非常大,很明显用邻接矩阵存不行,那么就要用到prim算法,即从一个点出发,每次朝路径最短的点走,直到走完所有点,详细见代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    
    const int maxn = 5010,inf = 1e8;
    
    using namespace std;
    int n, x[maxn], y[maxn],vis[maxn];
    double d[maxn],ans,temp;
    
    double jisuan(int x1, int y1, int x2, int y2)
    {
        return sqrt((double)(x1 - x2) * (x1 - x2) + (double)(y1 - y2) * (y1 - y2));
    }
    
    int main()
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
            scanf("%d%d", &x[i], &y[i]);
        for (int i = 1; i <= n; i++)
            d[i] = inf;
        d[1] = 0;
        int flag;
        for (int i = 1; i <= n; i++)
        {
            temp = inf;
            for (int j = 1; j <= n; j++)
                if (!vis[j] && d[j] < temp)
                {
                    temp = d[j];
                    flag = j;
                }
            if (temp == inf)
                break;
            vis[flag] = 1;
            ans += temp;
            for (int j = 1; j <= n; j++)
                if (!vis[j])
                {
                    double s = jisuan(x[flag], y[flag], x[j], y[j]);
                    if (s < d[j])
                        d[j] = s;
                }
                    
        }
        printf("%.2lf
    ", ans);
    
        return 0;
    }
  • 相关阅读:
    c# 虚拟路径转换为绝对路径
    Java基础——封装
    作为测试人,如何优雅的查看Log日志?
    学习整理
    记一次DataNode慢启动问题
    记一次DataNode慢启动问题
    记一次DataNode慢启动问题
    DataNode迁移方案
    C++学习笔记-模板
    C Primer Plus之指针
  • 原文地址:https://www.cnblogs.com/zbtrs/p/5801111.html
Copyright © 2011-2022 走看看