Prim和Kruskal求最小生成树

Prim:

算法步骤:

1.任意结点开始(不妨设为v1)构造最小生成树: 2.首先把这个结点(出发点)包括进生成树里, 3.然后在那些其一个端点已在生成树里、另一端点还未在生成树里的所有边中找出权最小的一条边, 4.并把这条边、包括不在生成树的另一端点包括进生成树, …。 5.依次类推,直至将所有结点都包括进生成树为止

Pascal的渣渣代码...

注:寻找最短的边那一步可以用堆优化,但那样还不如直接用Kruskal......

Reference:  http://www.nocow.cn/index.php/Prim%E7%AE%97%E6%B3%95

const vmax=1000;
var
w:array[1..vmax,1..vmax] of longint;
i,j,k,v,e:longint;
w:存储邻接矩阵
v:结点数
e:边数

procedure prim(v0:longint);
var flag:array[1..vmax] of boolean;  //flag:表示是否在树中。true是, false否
      min,prevk,nextk:longint;
begin
 fillchar(flag,sizeof(flag),0);
 flag[v0]:=true;           //STEP2
 for i:=1 to v-1 do          //最小生成树中有v-1条边 ,所以外层循环需要v-1次        //STEP5
   begin
    min:=maxlongint;

    for k:=1 to v do
      if flag[k] then
        //寻找在最小生成树中的点  k:当前在最小生成树中的点
        for j:=1 to v do          //STEP3
          //寻找与(最小生成树中的点)的距离最短的点。
          // j:当前要找的不在最小生成树中的点
          if (not flag[j]) and (w[k,j]<min) and (w[k,j]<>0) then
            紫色代码://判重:要找的点不能在最小生成树中
            红色代码://k与j必须相连!
            begin
            min:=w[k,j];
            nextk:=j;
            prevk:=k;
            //这条边从在最小生成树中的点出发 ,
            //扩展到当前不在最小生成树中的点。
            //prevk:=k,prevk为起点,在最小生成树中
            //nextk:=j,nextk为 终点,当前不在最小生成树中
            end;

    if min<>maxlongint then
      //如果找到了nextk这样的可以从当前最小生成树中扩展出来
      //(可以进入最小生成树)的点
      begin
      flag[nextk]:=true;        //将nextk这样的点加入最小生成树    //STEP4
      writeln(prevk,‘ ’,nextk,‘ ’,min);           //输出这条边
      end;
   end;
end;

begin
fillchar(w,sizeof(w),0);
readln(v,e);
for k:=1 to e do
 begin
 read(i,j);
 readln(w[i,j]);
 w[j,i]:=w[i,j];
 end;

prim(1);       //STEP1

end.

Kruskal:

算法步骤:

1、把图中的边按权值从小到大排序。 2、按从小到大的顺序依次向树中加边。       在添加每一条边(u,v)时,如果u和V两个点都已在树中,一旦添加,就回构成回路,所以放弃该边,在向后找下一条边。 3、直到添加n-1条边。

用并查集优化

#include <iostream>
using namespace std;

struct abc
{
    int x,y,dat;
};

struct abc e[1000];
int f[1000];
int i,j,k,ans,n,m,tx,ty,tmp;

int find(int x)
{
    if (x!=f[x])
        f[x]=find(f[x]);
    return f[x];
}

void iunion(int x,int y)
{
    int fx=find(x);
    int fy=find(y);
    if (fx!=fy)
        f[fy]=fx;
}

void qsort(int l,int r)
{
   int i,j,mid;
   struct abc t;
   i=l;
   j=r;
   mid=e[(l+r)/2].dat;
   do{
       while (e[i].dat<mid) i++;
       while (e[j].dat>mid) j--;
       if (!(i>j))
       {
           t=e[i];
           e[i]=e[j];
           e[j]=t;
           i++;
           j--;
       }
   }while (i<=j);
   if (l<j) qsort(l,j);
   if (i<r) qsort(i,r);
}

int main()
{

    cin>>n>>m;
    for (i=1;i<=m;i++)
    {
        cin>>tx>>ty>>tmp;
        e[i].x=tx;
        e[i].y=ty;
        e[i].dat=tmp;
    }

    for (i=1;i<=n;i++)
        f[i]=i;
    qsort(1,m);

    k=1;
    ans=0;
    for (i=1;i<=n-1;i++)
    {
        while (find(e[k].x)==find(e[k].y)) k++;
        iunion(e[k].x,e[k].y);
        ans=ans+e[k].dat;
        cout<<e[k].x<<" "<<e[k].y<<" "<<e[k].dat<<endl;
    }

    cout<<ans<<endl;
}

Prim和Kruskal求最小生成树

时间: 2024-08-02 02:48:42

Prim和Kruskal求最小生成树的相关文章

HDU6349-三原色图 Kruskal求最小生成树

三原色图 Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 134 Problem Description 度度熊有一张 n 个点 m 条边的无向图,所有点按照 1,2,?,n 标号,每条边有一个正整数权值以及一种色光三原色红.绿.蓝之一的颜色. 现在度度熊想选出恰好 k 条

Kruskal求最小生成树

1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn= 5e4+10; 4 const double eps= 1e-6; 5 const int inf = 0x3f3f3f3f; 6 const int mod =3; 7 typedef long long ll; 8 typedef long double ld; 9 int n,m; 10 int p[maxn]; 11 struct edge 12 { 1

[算法第一轮复习] kruskal求最小生成树算法

最小生成树算法即MST,有kruskal,prim两种算法,这里主要介绍kruskal 什么是最小生成树? 对于一个图,保证其中每个点都可以连通的最小的花费 1.算法核心 贪心+并查集 2.算法实现过程 克鲁斯卡尔算法 假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林.之后,从网的边集 E 中选取一条权值最小的边,若该

hdu 1233 还是畅通工程(kruskal求最小生成树)

还是畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 31362    Accepted Submission(s): 14083 Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路

【图论】信手拈来的Prim,Kruskal和Dijkstra

关于三个简单的图论算法 prim,dijkstra和kruskal三个图论的算法,初学者容易将他们搞混,所以放在一起了. prim和kruskal是最小生成树(MST)的算法,dijkstra是单源最短路径的算法. prim 最小生成树prim算法采用了贪心策略:把点分成两个集合,A为已被处理(已经在最小生成树中)的顶点,B为待处理的顶点,(A,B)也就是一个割.若边(u,v)满足u∈A,v∈B,那么(u,v)就是通过割(A,B)的一条边. 很自然的,会有一定数量的边会通过该割,其中权重最小的边

POJ 1679 The Unique MST (Kruskal 判最小生成树是否唯一)

The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 21646 Accepted: 7661 Description Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spanning Tree): Consider a connected, undirected

Prim算法和Kruskal算法求最小生成树

Prim算法 连通分量是指图的一个子图,子图中任意两个顶点之间都是可达的.最小生成树是连通图的一个连通分量,且所有边的权值和最小. 最小生成树中,一个顶点最多与两个顶点邻接:若连通图有n个顶点,则最小生成树中一定有n-1条边. Prim算法需要两个线性表来进行辅助: visited: 标记已经加入生成树的顶点:(它的功能可以由tree取代) 初始状态:生成树根节点为真,其它为0. tree: 记录生成树,tree[x]保存顶点x的直接根节点下标,若x为树的根节点则tree[x]为其自身. 初始状

最小生成树的两种算法:Prim和Kruskal算法

越来越明白了一个道理:你写不出代码的原因只有一个,那就是你没有彻底理解这个算法的思想!! 以前写过最小生成树,但是,水了几道题后,过了一段时间,就会忘却,一点也写不出来了.也许原因只有一个,那就是我没有彻底理解这两种算法. 主题: 其实,求最小生成树有两个要点,一个是权值最小,还有一个就是这个图必须是树.而Prim和Kruskal的不同之处在于两者选择的变量不同,Prim选择的是始终保持权值最小,然后逐个加点构建一棵树.而Kruskal则是始终保证是一棵树(虽然构建过程中不一定是真正的树,但并查

hdu1233还是畅通工程 最小生成树(prim或kruskal)

Problem Description 某省调查乡村交通状况,得到的统计表中列出了任意两村庄间的距离.省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可),并要求铺设的公路总长度为最小.请计算最小的公路总长度. Input 测试输入包含若干测试用例.每个测试用例的第1行给出村庄数目N ( < 100 ):随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间的距离.为简