• P1265 公路修建


    算法

    最小生成树+prim

    思路

    既然这题本质上就是Prim算法, 我就在这里写一写我对Prim算法的理解.

    两个最小生成树算法, 都有一个共同的思想: 这棵树是一点一点长大的; 并且每次生长, 都是贪心的.

    不同之处是: Kruscal算法是以边为中心的, 每次找最小的并且有用的边添加到树上;

    Prim算法是以点为中心的, 每次找离树最近的点添加到树上.

    我们可以把一棵树理解成一个有智能的生命, 可以感知它附近的点到它的距离. 每次生长枝条, 它都选择离它最近的那个点.

    点到树的距离, 是指树外一个点到树上的任意点的最小距离.

    所以,在代码实现的时候, 需要维护这样一个数组: 树外的点到树的距离. 所以, 还需要区分一下点究竟在树上还在树外.

    维护数组就是要做两件事: 更改数组和调用数组.

    何时更改: 树外的点到树的距离发生变化. 这种事只能在树生长了新的枝条的时候发生, 因为新加入的那个点可能更新了树到树外的某个点的距离. 同时, 新加入的那个点变成了树上的点.

    何时调用: 想扩张的时候, 找最近的树外点.

    一开始, 我们认为1号结点在树上, 把它到树的距离设为0; 其它结点的距离是INF.

    在调用完整个算法之后, 因为当一个节点变成树上节点后, 我们就不再更新它到树的距离, 所以, 原来的数组记录的就是它加入到树上时的连边长度. 对之求和, 就是树上所有边权之和.

    Prim算法的优势: 稠密图, 尤其是完全图. 因为在Kurscal算法中, 必须事先求出所有边的长度才能对之排序. 但是一个有5000节点的完全图, 这样做的空间开销是巨大的. Prim算法只在更新点到树的距离时需要用到边长, 因此对于这种给坐标的完全图, 可以现用现算.

    代码

    #include<bits/stdc++.h>
    #define For(i, m) for(register int i=1; i<=m; i++)
    #define INF 0x3f
    #define N 5123
    #define M
    using namespace std;
    struct POINT{
        long long x;
        long long y;
    
        long long operator* (const POINT &b) const {
            return (x-b.x)*(x-b.x)+(y-b.y)*(y-b.y);
        }
    }city[N];
    
    inline long long read(){
        long long x=0, sign=1; char c=getchar();
        while(c>'9' || c<'0') {if (c=='-') sign=-1;c=getchar();}
        while(c>='0' && c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*sign;
    }
    int n, m;
    bool v[N]; long long d[N];
    
    void prim(){
        memset(d, INF, sizeof(d));
        memset(v, 0, sizeof(v));
        d[1]=0;
        For(i, n-1){
            int x=0;
            For(j, n){
                if (!v[j] && (x==0 || d[j]<d[x])) x=j;
            }
            v[x]=1;
            For(y, n){
                if (!v[y]) d[y]=min(d[y], city[x]*city[y]);
            }
        }
    }
    int main(){
        n=read();
        For(i, n){
            city[i].x=read();
            city[i].y=read();
        }
        prim();
        double ans=0;
        For(i, n) ans+=sqrt((double)d[i]);
        printf("%.2f
    ", ans);
        return 0;
    }
    

      

     

  • 相关阅读:
    C# 依据鼠标坐标取网页内成员坐标.ie
    C# WebBrowser获取指定字符串的坐标
    C#获取网页中某个元素的位置,并模拟点击
    qq空间认证教程:借助企鹅媒体平台认证QQ公众空间
    QQ空间认证之数据篇
    QQ空间运营 怎么做一个QQ人气号?
    QQ空间|qq人气号怎么赚钱?
    QQ好友的价值玩法 及如何搞到几万好友?
    新媒体运营之如何月涨十万粉
    社群经济:如何利用社群做营销?
  • 原文地址:https://www.cnblogs.com/ruanmowen/p/12771568.html
Copyright © 2020-2023  润新知