图论——最小生成树①

RT

题目描述

国防部计划用无线网络连接若干个边防哨所。2 种不同的通讯技术用来搭建无线网络;

每个边防哨所都要配备无线电收发器;有一些哨所还可以增配卫星电话。

任意两个配备了一条卫星电话线路的哨所(两边都?有卫星电话)均可以通话,无论

他们相距多远。而只通过无线电收发器通话的哨所之间的距离不能超过 D,这是受收发器

的功率限制。收发器的功率越高,通话距离 D 会更远,但同时价格也会更贵。

收发器需要统一购买和安装,所以全部哨所只能选择安装一种型号的收发器。换句话

说,每一对哨所之间的通话距离都是同一个 D。你的任务是确定收发器必须的最小通话距

离 D,使得每一对哨所之间至少有一条通话路径(直接的或者间接的)。

输入输出格式

输入格式:

输入数据第 1 行,2 个整数 S 和 P,S 表示可安装的卫星电话的哨所

数,P 表示边防哨所的数量。接下里 P 行,每行两个整数 x,y 描述一个哨所的平面坐标

(x, y),以 km 为单位。

输出格式:

第 1 行,1 个实数 D,表示无线电收发器的最小传输距离,?确到小数点后两位。

输入输出样例

输入样例#1:

2 4
0 100
0 300
0 600
150 750

输出样例#1:

212.13

刚开始没读懂题,后来才直到,大概就是说有一些卫星设备,可以无花费的连边,就是有卫星设备的点之间,边的权值就是0;好像就会了,一个最小生成树;然后就有坑了错误的思路:每两个设备去掉一个边,s个设备去s/2个边,然后贪心删去;(呵呵)就像下图,假如有3个设备;其实,你只要在5,3,4放就行如果总的来说,就是你从两个设备开始,你每多加一个,你就能去一个边。OJBK.用prim,求出最小生成树的所有边长,然后找出第q-s大的;

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>

using namespace std;
struct data{int v,nxt;double val;}edge[260000];
int cnt,alist[600];
inline void add(int u,int v,double val)
{
    edge[++cnt].v=v;edge[cnt].val=val;
    edge[cnt].nxt=alist[u];alist[u]=cnt;
}
struct nod
{
    int num;double val;
    friend bool operator <(nod a,nod b){return a.val>b.val;}
};
double juli(double x1,double y1,double x2,double y2)
{
    double lon;
    lon=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    return lon;
}
double res[360000];
priority_queue <nod> pq;
int tim;
bool vis[600];double d[600];
int s,p;double x[600],y[600];
bool cmp(double a,double b)
{return a<b;
}
int main()
{
    scanf("%d%d",&s,&p);
    for(int i=1;i<=p;++i)
    {
        scanf("%lf %lf",&x[i],&y[i]);
    }
    for(int i=1;i<=p;++i)
    {
        for(int j=1;j<=p;++j)
        {
            if(i==j) continue;
            add(i,j,juli(x[i],y[i],x[j],y[j]));
        }
    }
    for(int i=1;i<=p;++i){d[i]=0x3f3f3f3f;}
    nod poi;poi.num=1;d[1]=0;poi.val=0;pq.push(poi);
    while(!pq.empty())
    {
        nod now=pq.top();pq.pop();if(vis[now.num])continue;
        vis[now.num]=true;res[++tim]=now.val;
        int nxt=alist[now.num];
        while(nxt)
        {
            int v=edge[nxt].v;
            double val=edge[nxt].val;
            if(d[v]>val&&vis[v]==false)
            {
                d[v]=val;nod poi;
                poi.num=v;poi.val=val;
                pq.push(poi);
            }
            nxt=edge[nxt].nxt;
        }
    }
        sort(res+1,res+1+p,cmp);
        printf("%0.2lf\n",res[p-s+1]);
}

                                                                        2018-02-07 16:39:53



原文地址:https://www.cnblogs.com/AidenPearce/p/8427355.html

时间: 2024-11-05 11:39:28

图论——最小生成树①的相关文章

图论 --- 最小生成树 + 剪枝 + 路径合并

Connect the Cities Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9941    Accepted Submission(s): 2827 Problem Description In 2100, since the sea level rise, most of the cities disappear. Thoug

HDU 1162 Eddy&#39;s picture(图论-最小生成树)

题目如下: Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7267    Accepted Submission(s): 3676 Problem Description Eddy begins to like painting pictures recently ,he is sure of himse

图论-最小生成树

今天听了CLRS的第二作者讲的课程,关于最小生成树的算法. 其实就是先模拟一下小样例(不是单纯模拟,而是发现其中的规律,要思考) 然后发现最优子结构-如果(u,v)是一条唯一连接两点的边,那么将原图拆分为两块(一块包含u,一块包含v),两图分别最优解+dist[u,v]就是原图的最优解了. 然后发现这样做会有很多很多的重叠子问题:把每次的(u,v)换一换顺序就一堆重叠子问题.于是就有动态规划的思路了-- 别急! 这里还有一个性质:如果(u,v)在当前图中边权最小,则(u,v)必在此图的最小生成树

数据结构之 图论---最小生成树(prim + kruskal)

图结构练习——最小生成树 Time Limit: 1000MS Memory limit: 65536K 题目描述 有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的.现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市. 输入 输入包含多组数据,格式如下. 第一行包括两个整数n m,代表城市个数和可以修建的公路个数.(n<=100) 剩下m行每行3个正整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c. 输出

【uva 1151】Buy or Build(图论 最小生成树)

题意:平面上有N个点(1≤N≤1000),若要新建边,费用是2点的欧几里德距离的平方.另外还有Q个套餐,每个套餐里的点互相联通,总费用为Ci.问让所有N个点连通的最小费用.(2组数据的输出之间要求有换行) 解法:利用二进制枚举套餐,时间复杂度是O(2QN2+N2logN).关于时间复杂度,枚举:二进制枚举为2Q,Kruskal为ElogE≍E≍N2:边排序:ElogE≍E≍N2.总的相加. 紫书上提到一个优化:不加任何套餐跑一遍MST(最小生成树),没有选的边便删除掉,因为以后加了套餐之后也选不

Light OJ 1029- Civil and Evil Engineer (图论-最小生成树)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1029 题目大意:一个发电站,给n座房子供电, 任意房子之间有电线直接或者间接相连接, 现在想知道需要连接这些房子花费的平均电线长度.平均电线长度 = (最长电线长度 + 最短电线长度)/ 2: 解题思路:裸的最小生成树 代码如下: #include <bits/stdc++.h> using namespace std; const int N = 1003; struct

图论-最小生成树-Kruskal算法

有关概念: 最小生成树:在连通图G中,连接图G所有顶点且总权最小的边构成的树 思路: 首先对边按权从小到大排序,紧接着枚举每一条边,如果两个结点的祖先结点不同(并查集),则连上此边,直到边数等于结点数-1即可 邻接矩阵输入,用类邻接表存储方式存边 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 #define MAXN 5 #define MAXM 6 int father[MAXN],n,m,cn

图论——最小生成树prim+邻接表+堆优化

今天学长对比了最小生成树最快速的求法不管是稠密图还是稀疏图,prim+邻接表+堆优化都能得到一个很不错的速度,所以参考学长的代码打出了下列代码,make_pair还不是很会,大体理解的意思是可以同时绑定两种元素(和struct差不多)但加入堆的时候以第一个元素来进行优先队列,建立的是大根堆由于每次要选出最小的边所以把边取反,最小的那个边加上符号就变成最大的了,大体上就是这样.prim的思想. #include<iostream> #include<cstdio> #include&

图论 - 最小生成树 - Kurskal算法 - 道路升级

问题描述 Z国有 n 个城市和 m 条双向道路,每条道路连接了两个不同的城市,保证所有城市之间都可以通过这些道路互达.每条道路都有一个载重量限制,这限制了通过这条道路的货车最大的载重量.道路的编号从 1 至 m .巧合的是,所有道路的载重量限制恰好都与其编号相同. 现在,要挑选出若干条道路,将它们升级成高速公路,并满足如下要求: 所有城市之间都可以通过高速公路互达. 对于任意两个城市 u,v 和足够聪明的货车司机:只经过高速公路从 u 到达 v 能够装载货物的最大重量,与经过任意道路从 u 到达