• 最小生成树之Prim的应用


    现在是凌晨时分 本来很早就想写了 被一道搜索题卡到现在 至今没有A出 等A出以后 一定要写出来 ....

    Prim:它是 基于 图的顶点 的算法

    其实 这个算法 是很容易理解的

    首先 你任意选取一个点 加入MST集合中 这里的MST即最小生成树集合

    然后你对所有不属于MST的点 进行循环遍历寻找权值最小的边

    并且 再每加入一个点后 就刷新其余点到这个MST集合的相对最短距离(这是核心步骤)

    个人 感觉Prim算法 还是很基础的 当你不考虑heap优化的情况下

    我们还是 那道题说说吧

    题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=38

     1 #include <stdio.h>
     2 #include <string.h>
     3 #define MAX 100000000
     4 int map[505][505];//邻接矩阵
     5 int dis[505];//距离 并且指这条边是以dis[i]的i为结尾的
     6 int visited[505];
     7 int n,m;
     8 
     9 int prim()
    10 {
    11     int i,j,k,ans=0,min,t;
    12     memset(visited,0,sizeof(visited));//起初标记所有点都未被访问
    13     for(i=1;i<=n;i++)
    14         dis[i]=map[1][i];//所有最小权值边起初都是以相同的起始点1开始
    15     visited[1]=1;//从1开始访问
    16     for(i=1;i<n;i++)//因为是最小生成树 所以当有n个顶点的时候 只有n-1条边
    17     {
    18         min=MAX;//将Min设置的 无穷大 以便来标记
    19         for(j=2;j<=n;j++)
    20         {
    21             if( !visited[j] && dis[j]<min )//j的要求未被访问 并且可以得到相对最小距离
    22             {
    23                 min=dis[j];
    24                 t=j;
    25             }
    26         }
    27         if(min==Max)//如果这个if成立相当于 上面没有一个j进入MST中 所有可以直接break
    28               break;
    29         ans+=min;
    30         visited[t]=1;
    31 
    32         for(k=2;k<=n;k++)
    33         {
    34             if( !visited[k] && dis[k]> map[t][k] )//这边 我用大于号 才能刷新最下值
    35                 dis[k]=map[t][k];
    36         }
    37 
    38     }
    39     return ans;
    40 }
    41 
    42 int main()
    43 {
    44     int t,a,b,c,i,j,min;
    45     scanf("%d",&t);
    46     while (t--)
    47     {
    48         scanf("%d %d",&n,&m);
    49         for(i=1;i<=n;i++)
    50         {
    51             for(j=1;j<=n;j++)
    52                 map[i][j]=MAX;
    53         }
    54         for(i=1;i<=m;i++)
    55         {
    56             scanf("%d%d%d",&a,&b,&c);
    57             map[a][b]=map[b][a]=c;
    58         }
    59         min=MAX;
    60         for(i=1;i<=n;i++)
    61         {
    62             scanf("%d",&a);
    63             if(a<min)
    64                 min=a;
    65         }
    66         printf("%d
    ",min+prim());
    67     }
    68 }
    View Code

    这边 我给出的是邻接矩阵的实现方式  你可以自己去实现 邻接表的方式   而我会在下次 讲到欧拉图的时候 使用邻接表

    其实 这段以前写过的代码 还有很多可以优化的细节 例如:vis数组 用bool实现   MAX的设置使用16进制来实现

    我还想提的一点是: Prim算法的思想 与 最短路中Dijkstra的思想 实在是太像了

    最大的区别就是:Dijk数组含义上的不同:这里是指顶点到MST集合的最短距离 Dijkstra算法中是指顶点到起始点的最短距离

    我想 对于每个算法 了解它的思想 才是最重要的

    just follow your heart
  • 相关阅读:
    android activity的生命周期和启动模式
    Android ListView的基本应用
    android WebView技术笔记(存储技术)
    Android RecyclerView初探
    Android-----ListView组件使用(实现点击选择)
    Android-----CheckBox复选使用(实现简单选餐)
    Android-----RadioButton单选使用(实现简单温度转换)
    Android-----Intent通过startActivityForResult(Intent intent , int 标志符)启动新的Activity
    Android-----Intent中通过startActivity(Intent intent )显式启动新的Activity
    Android-----Intent中通过startActivity(Intent intent )隐式启动新的Activity
  • 原文地址:https://www.cnblogs.com/radical/p/3663120.html
Copyright © 2020-2023  润新知