zoukankan      html  css  js  c++  java
  • 最小生成树 普里姆算法

    题目来源  POJ2349

    在介绍什么是最小生成树之前先介绍什么是加权图

    在之前已经默认了解了无向图(并查集)以及有向无环图(拓扑排序),那么最小生成树可以理解是一个加权的无向图,那么我们要坐的就是在这个无向图中间找出一条路径,使这条路径可以连接所有的结点,并且在所有的情况中,该路径的权值和最小,这一条路径我们称之为最小生成树。(注意一定要区别开最短路)

    普里姆算法

    简单的说就是从起点开始,不断的从所有点中选出能到达集合V(即为MST的顶点的集合)的最小权值的点,直到这个集合包含了所有的节点,也就是一个贪心过程,集合V指的就是已经被选入为最小生成树的点的集合。

    下面看这个题目

    首先简单说一下题意,有S个哨所,为了让这S个哨所可以互相联络,有两种方式,一种是通过卫星,这一种比较高级(任意两个拥有卫星频道的哨所可以直接联系,不用管之间的位置关系如何),但是卫星频道只有P个,还有一种就比较低级,就是通过无线电收发器,每个无线电收发器都有限制距离D,D越大,成本越高,也就是说两个哨所越远,就需要功率越大的无线电收发器,那么问题就是求需要的最小的D是多少才能把所有哨所都连接起来(直接或间接)。

    理解题意之后我们不难发现,该题的思路就是找到最小生成树,然后并输出权值最长的边就可以了(删去卫星频道之后),每条边的权值即为两点之间的距离。

    首先我们需要建图,这里用的是邻接矩阵来建图,但是在普里姆算法中,遍历图的所有顶点来确定D最小的顶点复杂度为O(|V|2)

    接下来是代码以及相应的注释

     1 #include<iostream>
     2 #include<cstring>
     3 #include<math.h>
     4 #include<queue>
     5 #include<iomanip>
     6 #include<algorithm>
     7 using namespace std;
     8 static const double INFTY=(1<<21);
     9 static const int BLACK=2;//选定的状态
    10 static const int GRAY=1;//候选的状态
    11 static const int WHITE=0;//为选择的状态
    12 struct stu{int x,y;}len[505];
    13 double dis[505][505];//存两点之间的距离
    14 double d[50000];//记录与V连接的顶点的边的最小权值
    15 int calor[505];//记录V的访问状态
    16 int p[505];//记录MST中顶点v的父节点
    17 double minv;
    18 priority_queue<double> q;
    19 int main()
    20 {
    21     //freopen("C:\Users\16599\Desktop\in.txt","r",stdin);
    22     int T,u;
    23     int weixin,state;
    24     cin>>T;
    25     for(int l=1;l<=T;l++)
    26     {
    27         memset(dis,0,sizeof(dis));
    28         memset(calor,WHITE,sizeof(calor));
    29         memset(p,-1,sizeof(p));
    30         cin>>weixin>>state;
    31         for(int i=1;i<=state;i++)
    32             cin>>len[i].x>>len[i].y;
    33     for(int i=1;i<state;i++)
    34         for(int j=i+1;j<=state;j++)
    35             dis[i][j]=dis[j][i]=sqrt((len[j].x-len[i].x)*(len[j].x-len[i].x)+(len[j].y-len[i].y)*(len[j].y-len[i].y));
    36             for(int i=1;i<=state;i++)
    37                 d[i]=INFTY;//建图的过程
    38             d[1]=0;//选定起点
    39     while(true)
    40     {
    41         minv=INFTY;
    42         u=-1;
    43         for(int i=1;i<=state;i++)//找到连接集合V权值最小的点
    44         {
    45             if(minv>d[i]&&calor[i]!=BLACK)
    46             {
    47                 u=i;
    48                 minv=d[i];
    49                 //cout<<minv<<"  "<<i<<endl;
    50             }
    51         }
    52         if(u==-1)//MST已建成,结束
    53         {
    54             break;
    55         }
    56         calor[u]=BLACK;//将选好的点加入到V中
    57         for(int v=1;v<=state;v++)//更新连接V的所有点的状态以及最小权值
    58         {
    59             if(calor[v]!=BLACK&&dis[u][v]!=INFTY)
    60             {
    61                 if(d[v]>dis[u][v])
    62                 {
    63                     d[v]=dis[u][v];
    64                     p[v]=u;
    65                     calor[v]=GRAY;
    66                 }
    67             }
    68         }
    69         while(!q.empty())//更新MST
    70             q.pop();
    71             for(int i=1;i<=state;i++)
    72                 if(p[i]!=-1)
    73                     q.push(dis[i][p[i]]);
    74     }
    75     while(1)
    76     {
    77         if(weixin==1)
    78             break;
    79         weixin--;
    80         q.pop();
    81     }
    82     cout<<fixed<<setprecision(2)<<q.top()<<endl;
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    js关于页面坐标api
    js面向对象之创建对象
    Web前端安全问题
    js操作cookie
    css清除浮动
    块级格式化上下文(block formatting context)
    《python核心编程》笔记——系统限制
    《python核心编程》笔记——文件的创建、读取和显示
    黑客们的故事连载十二 “蠕虫来袭”:莫里斯
    黑客们的故事连载十一 下村努—虚拟战争追逐
  • 原文地址:https://www.cnblogs.com/zlhdbk/p/10797350.html
Copyright © 2011-2022 走看看