题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1162

【题目大意】

给你n个点的坐标,让你找到联通n个点的一种方法。保证联通的线路最短,典型的最小生成树问题。

方法一 。 通过不断找到最小的边来找到终于结果。

Kruskal 算法

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
struct node{
double a,b;
int po;
}point[110];
const int maxe = 10010;
struct Edge{
int v1,v2;
double length;
}edge[maxe];
bool cmp(const Edge&a, const Edge&b){
return a.length<b.length;
}
int n; int cnt;
int father[110];
void MakeSet(){
for(int i=0;i<=n;i++){
father[i]=i;
}
}
int Find(int x){
int xroot = x;
while(xroot!=father[xroot])
xroot=father[xroot];
while(x!=xroot){
int tmp = father[x];
father[x]=xroot;
x = tmp;
}
return xroot;
}
void Union(int x,int y){
int xr=Find(x);
int yr=Find(y);
if(xr==yr) return ;
else{
father[xr]=yr;
}
}
void Kruskal(){
int edgenum=0;
double ans=0;
for(int i=0;i<cnt&&edgenum!=n-1;i++){
if(Find(edge[i].v1)!=Find(edge[i].v2)){
ans+=edge[i].length;
Union(edge[i].v1,edge[i].v2);
edgenum++;
}
}
printf("%.2lf\n",ans);
}
double disc(node x, node y){
return (double)sqrt((x.a-y.a)*(x.a-y.a)+(x.b-y.b)*(x.b-y.b));
}
int main(){
double a,b;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>point[i].a>>point[i].b;
point[i].po=i+1;
}
MakeSet();
cnt=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
double dis= disc(point[i],point[j]); //求出点 与 点 之 间 的距 离, 列出全部的边。 edge[cnt].v1=point[i].po;
edge[cnt].v2=point[j].po;
edge[cnt].length=dis;
cnt++;
}
}
sort(edge,edge+cnt,cmp);
Kruskal();
}
return 0;
}

方法二 prim算法, 通过不断找到距离 最小生成树所在集合全部点中 距离最小的点。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
#define maxn 110
#define INF 0xfffffff
struct node{
double a,b;
int po;
}point[maxn];
int n;
struct node2{
int v;
double dis;
node2(int v=0, double dis=0):v(v),dis(dis){}
};
vector <node2> G[maxn]; //用邻接链表储存图
const int maxe = 10010;
bool intree[maxn];
double minDist[maxn];
void init(){
for(int i=0;i<maxn;i++ ){
minDist[i]=INF;
G[i].clear();
intree[i]=false;
}
}
double prim(int s){
intree[s] = true;
for(int i=0;i<G[s].size();i++){
int vex = G[s][i].v;
minDist[vex] = G[s][i].dis; //初始化 , 将与起点相联的 点与起点的距离“显化”
}
double ans = 0;
for(int nodeNum = 1 ;nodeNum<=n-1;nodeNum++){ //还剩下 n-1 个点未找
double tmpMin = INF;
int addNode;
for(int i=1;i<=n;i++){
if(!intree[i]&&minDist[i]<tmpMin){ //仅仅有经过显化的 且没有入最小生成树的点 才干通过比較
tmpMin = minDist[i]; //不断更新,找到最短的
addNode = i;
}
}
intree[addNode] = true; //入树
ans+=tmpMin;
for(int i=0; i < G[addNode].size();i++){ //更新 将新增加节点的 相联节点“显化”
int vex = G[addNode][i].v;
if(!intree[vex]&&G[addNode][i].dis<minDist[vex]) //更新未入最小生成树的节点,与之的最短距离。
minDist[vex] = G[addNode][i].dis;
}
}
return ans;
}
double disc(node x, node y){
return (double)sqrt((x.a-y.a)*(x.a-y.a)+(x.b-y.b)*(x.b-y.b));
}
int main(){
double a,b;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>point[i].a>>point[i].b;
point[i].po=i+1;
}
init();
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
double dis= disc(point[i],point[j]);
G[point[i].po].push_back(node2(point[j].po,dis));
G[point[j].po].push_back(node2(point[i].po,dis));
}
}
double ans = prim(1);
printf("%.2lf\n",ans);
}
return 0;
}

最新文章

  1. HBase配置项详解
  2. Asp:Button控件onclick事件无刷新页面提示消息
  3. 使用RazorEngine对ASP.NET MVC的Views进行UnitTest
  4. 每天一个linux命令(38):vmstat命令
  5. 转--Android实用的代码片段 常用代码总结
  6. 实时阴影渲染(一):PSSM平行分割阴影图
  7. 多线程程序设计学习(10)Future pattern
  8. 兼容IE与firefox、chrome的css 线性渐变(linear-gradient)
  9. Hacker(25)----病毒攻防之认识病毒
  10. C#中的USB库 WinUSB
  11. SpringMVC中Controller
  12. python3.5 安装lxml
  13. org.apache.commons.beanutils.BeanMap简单使用例子
  14. NYOJ--27--dfs--水池数目
  15. sed 变量替换和Linux的特殊符号大全
  16. 第二次作业:软件分析之Steam的前世今生
  17. 理解Python闭包概念
  18. bash vim等常用命令
  19. C++类的大小计算
  20. 更新合并数组的es6方法

热门文章

  1. 第八篇:python基础_8 面向对象与网络编程
  2. P3141 [USACO16FEB]围栏Fenced In_Platinum
  3. [bzoj4945][Noi2017]游戏
  4. GYM - 101620 J.Justified Jungle
  5. Windows彻底删除不用的dc
  6. Matlab 几种卷积的实现与比较(conv与filter,conv2与filter2)
  7. 汕头市队赛 SRM10 T1模拟只会猜题意
  8. HDU 3853 LOOP (概率DP求期望)
  9. Windows注册与删除mysql服务
  10. vifx.y-emu 和 vifx.y 和 tapx.y