Prim POJ 2031 Building a Space Station

题目传送门

题意:给出n个三维空间的球体,球体是以圆心坐标+半径来表示的,要求在球面上建桥使所有的球联通,求联通所建桥的最小长度。

分析:若两点距离大于两半径和的长度,那么距离就是两点距离 - 半径和,否则为0,Prim写错了,算法没有完全理解

/************************************************
* Author        :Running_Time
* Created Time  :2015/10/25 12:00:48
* File Name     :POJ_2031.cpp
 ************************************************/

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e2 + 10;
const int E = N * N;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-10;

bool vis[N];
double d[N];
int head[N];
int n, m, e;
int dcmp(double x)  {       //三态函数,减少精度问题
    if (fabs (x) < EPS) return 0;
    else    return x < 0 ? -1 : 1;
}
struct Point    {
    double x, y, z, a;
    Point () {}
    Point (double x, double y, double z, double a) : x (x), y (y), z (z), a (a) {}
    Point operator - (const Point &r) const {       //向量减法
        return Point (x - r.x, y - r.y, z - r.z, 0);
    }
};
typedef Point Vector;       //向量的定义
Point read_point(void)   {      //点的读入
    double x, y, z, r;
    scanf ("%lf%lf%lf%lf", &x, &y, &z, &r);
    return Point (x, y, z, r);
}
double dot(Vector A, Vector B)  {       //向量点积
    return A.x * B.x + A.y * B.y + A.z * B.z;
}
double length(Vector A) {       //向量长度,点积
    return sqrt (dot (A, A));
} 

struct Edge {
    int v, nex;
    double w;
    Edge () {}
    Edge (int v, double w, int nex) : v (v), w (w), nex (nex) {}
    bool operator < (const Edge &r) const   {
        return w > r.w;
    }
}edge[E];

void init(void) {
    memset (head, -1, sizeof (head));
    e = 0;
}

void add_edge(int u, int v, double w)   {
    edge[e] = Edge (v, w, head[u]);
    head[u] = e++;
}

double Prim(int s) {
    memset (vis, false, sizeof (vis));
    for (int i=0; i<n; ++i) d[i] = 1e9;
    priority_queue<Edge> Q;
    for (int i=head[s]; ~i; i=edge[i].nex)  {
        int v = edge[i].v;  double w = edge[i].w;
        if (d[v] > w)   {
            d[v] = w;   Q.push (Edge (v, d[v], 0));
        }
    }
    vis[s] = true;  d[s] = 0;
    double ret = 0;
    while (!Q.empty ()) {
        int u = Q.top ().v; Q.pop ();
        if (vis[u]) continue;
        vis[u] = true;  ret += d[u];
        for (int i=head[u]; ~i; i=edge[i].nex)  {
            int v = edge[i].v;  double w = edge[i].w;
            if (!vis[v] && d[v] > w)   {
                d[v] = w;    Q.push (Edge (v, d[v], 0));
            }
        }
    }
    return ret;
}

Point p[N];
int main(void)    {
    while (scanf ("%d", &n) == 1)   {
        if (!n) break;
        for (int i=0; i<n; ++i) {
            p[i] = read_point ();
        }
        init ();
        for (int i=0; i<n; ++i) {
            for (int j=i+1; j<n; ++j)   {
                double dis = length (p[i] - p[j]);
                double len = p[i].a + p[j].a;
                if (dcmp (dis - len) <= 0)   {
                    add_edge (i, j, 0);
                    add_edge (j, i, 0);
                }
                else    {
                    add_edge (i, j, dis - len);
                    add_edge (j, i, dis - len);
                }
            }
        }
        printf ("%.3f\n", Prim (0));
    }

    return 0;
}
时间: 2024-10-03 21:54:13

Prim POJ 2031 Building a Space Station的相关文章

ZOJ 1718 POJ 2031 Building a Space Station 修建空间站 最小生成树 Kruskal算法

题目链接:ZOJ 1718 POJ 2031 Building a Space Station 修建空间站 Building a Space Station Time Limit: 2 Seconds      Memory Limit: 65536 KB You are a member of the space station engineering team, and are assigned a task in the construction process of the statio

poj 2031 Building a Space Station 【最小生成树 Prim】

Building a Space Station Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5778   Accepted: 2874 Description You are a member of the space station engineering team, and are assigned a task in the construction process of the station. You ar

POJ 2031 Building a Space Station

Building a Space Station Time Limit: 1000ms Memory Limit: 30000KB This problem will be judged on PKU. Original ID: 2031 64-bit integer IO format: %lld      Java class name: Main You are a member of the space station engineering team, and are assigned

poj 2031 Building a Space Station【最小生成树prime】【模板题】

Building a Space Station Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5699   Accepted: 2855 Description You are a member of the space station engineering team, and are assigned a task in the construction process of the station. You ar

POJ 2031 Building a Space Station (最小生成树)

Building a Space Station Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5173   Accepted: 2614 Description You are a member of the space station engineering team, and are assigned a task in the construction process of the station. You ar

POJ - 2031 Building a Space Station (prim)

题意:给出球形空间站数目N,以及各个空间站的三维坐标x,y,z 以及 半径r ,求将所有空间站连接的最小cost (cost就等于空间站之间的距离) 如果接触,包含,或者相交则不需要搭建桥 思路:还是一道最小生成树的题目,我们先记录每个空间站的信息,然后将所有空间站两两相连接,如果 如果接触,包含,或者相交 我们就把cost 置为1 ,否则就用距离半径之和. 把每个空间站用一个标号表示,然后记录到 向前星中 . 用prim算法 去找最小生成树即可 . 还有一点要注意的是,最后结过的输出:G++下

POJ - 2031 Building a Space Station(计算几何+最小生成树)

http://poj.org/problem?id=2031 题意 给出三维坐标系下的n个球体,求把它们联通的最小代价. 分析 最小生成树加上一点计算几何.建图,若两球体原本有接触,则边权为0:否则边权为它们球心的距离-两者半径之和.这样来跑Prim就ok了.注意精度. #include<iostream> #include<cmath> #include<cstring> #include<queue> #include<vector> #in

zoj 1718 poj 2031 Building a Space Station

最小生成树,用了Kruskal算法.POJ上C++能过,G++不能过... 算出每两个圆心之间的距离,如果距离小于两半径之和,那么这两个圆心之间的距离直接等于0,否则等于距离-R[i]-R[j]. #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; const int maxn = 10100; struct abc{ i

[2016-04-14][POJ][203][Building a Space Station]

时间:2016-04-14 21:43:30 星期四 题目编号:[2016-04-14][POJ][203][Building a Space Station] 题目大意:给定n个球体,每个球体可能重合,可能包含,可能分离,问把每个球体连接起来(重合和包含看做已经连接),至少需要多长的路 分析:最小生成树,边权为 max(0,disij?ri?rj)max(0,disij?ri?rj),即重合和内含,边权为0 #include<cstdio> #include<cstring> #