对于一个带权的无向连通图,其每个生成树所有边上的权值之和可能不同,我们把所有边上权值之和最小的生成树称为图的最小生成树

普里姆算法是以其中某一顶点为起点逐步寻找各个顶点上最小权值的边来构建最小生成树。

其中运用到了回溯,贪心的思想。

----------2018年5月24日补:

  #begin

    根据定义我们可知,求一个图的最小生成树的时候,一定会将所有的点都连接起来,也就是说,我们从任何一个点出发都可以得到这个图的最小生成树,那么我这里暂定从0出发,寻找到和0相连的点中最小的权值,作为连接0这一个点的边(如果有相同的最小权值,则视要求处理),将0这一个点设置为不可访问,同时保存此时的连接点,将求到的这一个点做和0一样相同的处理...处理出n个点就可以求得这个图的最小生成树了(如果不能处理出n个点,那么此图的最小生成树也就不存在)。

  #end

废话少说,直接上题吧!这些东西多练就好!

一、最小生成树:

题目描述
求一个连通无向图的最小生成树的代价(图边权值为正整数)。
输入
第 一行是一个整数N(1<=N<=20),表示有多少个图需要计算。以下有N个图,第i图的第一行是一个整数M(1<=M& lt;=50),表示图的顶点数,第i图的第2行至1+M行为一个M*M的二维矩阵,其元素ai,j表示图的i顶点和j顶点的连接情况,如果 ai,j=0,表示i顶点和j顶点不相连;如果ai,j>0,表示i顶点和j顶点的连接权值。
输出
每个用例,用一行输出对应图的最小生成树的代价。
样例输入
1
6
0 6 1 5 0 0
6 0 5 0 3 0
1 5 0 5 6 4
5 0 5 0 0 2
0 3 6 0 0 6
0 0 4 2 6 0
样例输出

15

//Asimple
#include <stdio.h>
#include <iostream>
#include <string.h> using namespace std;
#define INF 0xffffff
const int maxn = 55;
int G[maxn][maxn];//建图
int T, n; int prim()
{
int Min, sum = 0;
int adv[maxn]; //保存定点下标
int lowc[maxn]; //保存权值 adv[0] = lowc[0] = 0 ;
//初始化
for(int i=1; i<n; i++)
{
lowc[i] = G[0][i];//先放入 第0行 的所有权值
adv[i] = 0 ;
} //构建过程
for(int i=1; i<n; i++)
{
Min = INF ;
int j = 1 ;
int k = 0 ; while( j < n )
{
if( lowc[j]!=0 && lowc[j]<Min)
{
Min = lowc[j] ;
k = j ;
}
j ++ ;
}
sum += G[adv[k]][k] ;//计算最小权值
//printf("%d,%d",adv[k],k);//打印节点
lowc[k] = 0 ; //逐行遍历接下来的k个顶点
for(int l=1; l<n; l++)
{
if( lowc[l]!=0 && G[k][l] < lowc[l] )
{
lowc[l] = G[k][l] ;
adv[l] = k ;
}
}
}
return sum ;
} int main()
{
cin >> T ;
while( T -- )
{
cin >> n ;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
cin >> G[i][j];
if( G[i][j] == 0 && i!=j )
G[i][j] = INF ;
}
cout << prim() << endl ;
} return 0;
}

二、判断最小生成树是否唯一

题目描述

给出一个连通无向图,请判断其最小生成树是否是唯一的。

定义1(生成树):给出一个连通无向图G=(V,E),G的一颗生成树被标记为T=(V,E),则具有以下性质:

1)V'=V;

2)T是连通无回路的。

定义2(最小生成树):给出一个边带权的连通无向图G=(V,E),G 的最小生成树T=(v,E)是具有最小总耗费的生成树。T的总耗费表示E' 中所有边的权值的和。

输入

第 一行给出一个整数t(1<=t<=20),表示测试用例数,每个测试用例表示一个图,测试用例的第一行给出两个整数n,m(1<=n<=100),分别表 示顶点和边的数目,后面的m行每行是一个三元组(xi,yi,wi),表示xi和yi通过权值为wi的边相连。任意两个节点间至多只有一条边相连。

输出

对于每个测试用例,如果MST是唯一的,输出其总耗费;否则输出字符串'Not Unique!'.

样例输入
2
3 3
1 2 1
2 3 2
3 1 3
4 4
1 2 2
2 3 2
3 4 2
4 1 2
样例输出

3

Not Unique!

#include <stdio.h>
#include <iostream>
#include <string.h> using namespace std;
#define INF 0xffffff
const int maxn = 55;
int G[maxn][maxn];//建图
int T, n, m, x, y, num; void prim()
{
int Min, sum = 0;
int adv[maxn]; //保存定点下标
int lowc[maxn]; //保存权值
bool flag = false ; adv[0] = lowc[0] = 0 ;
//初始化
for(int i=1; i<n; i++)
{
lowc[i] = G[0][i];//先放入 第0行 的所有权值
adv[i] = 0 ;
} //构建过程
for(int i=1; i<n; i++)
{
Min = INF ;
int j = 1 ;
int k = 0 ; while( j < n )
{
if( lowc[j]!=0 && lowc[j]<=Min)
{
if( lowc[j] == Min ) flag = true ;
Min = lowc[j] ;
k = j ;
}
j ++ ;
}
sum += G[adv[k]][k] ;//计算最小权值
lowc[k] = 0 ; //逐行遍历接下来的k个顶点
for(int l=1; l<n; l++)
{
if( lowc[l]!=0 && G[k][l] < lowc[l] )
{
lowc[l] = G[k][l] ;
adv[l] = k ;
}
}
}
if( flag ) cout << "Not Unique!" << endl ;
else cout << sum << endl ;
} int main()
{
cin >> T ;
while( T -- )
{
cin >> n >> m ;
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
if( i == j ) G[i][j] = 0 ;
else G[i][j] = INF ;
}
for(int i=0; i<m; i++)
{
cin >> x >> y >> num ;
G[x-1][y-1] = num ;
G[y-1][x-1] = num ;
}
prim();
} return 0;
}

2018年4月1日更正:

上面的代码过不了  POJ 1679。谢谢指点~~   今天更改了下自己的程序。

18390068 Asimple 1679 Accepted 312K 16MS C++ 1483B 2018-04-01 20:08:48
//Asimple
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
#define INF 0xffffff
typedef long long ll ;
const int maxn = +;
int n, T, num, cnt, x, y, t, m, w;
int Map[maxn][maxn]; void prim() {
int lowc[maxn];
for(int i=; i<=n; i++) lowc[i] = Map[][i];
int sum = ;
bool flag = false; for(int l=; l<n; l++) {
int Min = INF;
int k = ;
for(int j=; j<=n; j++) {
if( lowc[j]!= && Min > lowc[j] ) {
k = j;
Min = lowc[j];
}
}
if( Min == INF ) break;
sum += Min;
int cnt = ;
for(int i=; i<=n; i++)
if( Map[k][i] == lowc[k] )
cnt ++;
if( cnt > ) {
flag = true;
break;
}
lowc[k] = ; for(int i=; i<=n; i++) {
if( lowc[i] > Map[k][i] ) {
lowc[i] = Map[k][i];
}
}
} if( flag ) cout << "Not Unique!" << endl;
else cout << sum << endl;
} void input() {
ios_base::sync_with_stdio(false);
cin >> T;
while( T -- ) {
cin >> n >> m;
for(int i=; i<=n; i++) {
for(int j=; j<=n; j++) {
Map[i][j] = i==j?:INF;
}
}
while( m -- ) {
cin >> x >> y >> w;
Map[x][y] = min(Map[x][y], w);
Map[y][x] = Map[x][y];
}
prim();
}
} int main() {
input();
return ;
}

ACM第四站————最小生成树(普里姆算法)的更多相关文章

  1. 图->连通性->最小生成树(普里姆算法)

    文字描述 用连通网来表示n个城市及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价.对于n个定点的连通网可以建立许多不同的生成树,每一棵生成树都可 ...

  2. ACM第四站————最小生成树(克鲁斯卡尔算法)

    都是生成最小生成树,库鲁斯卡尔算法与普里姆算法的不同之处在于——库鲁斯卡尔算法的思想是以边为主,找权值最小的边生成最小生成树. 主要在于构建边集数组,然后不断寻找最小的边. 同样的题目:最小生成树 题 ...

  3. 最小生成树---普里姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)

    普里姆算法(Prim算法) #include<bits/stdc++.h> using namespace std; #define MAXVEX 100 #define INF 6553 ...

  4. 图解最小生成树 - 普里姆(Prim)算法

    我们在图的定义中说过,带有权值的图就是网结构.一个连通图的生成树是一个极小的连通子图,它含有图中全部的顶点,但只有足以构成一棵树的n-1条边.所谓的最小成本,就是n个顶点,用n-1条边把一个连通图连接 ...

  5. 查找最小生成树:普里姆算法算法(Prim)算法

    一.算法介绍 普里姆算法(Prim's algorithm),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之 ...

  6. 普里姆算法(Prim)

    概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图(带权图)里搜索最小生成树.即此算法搜索到的边(Edge)子集所构成的树中,不但包括了连通图里的所有顶点(Vertex)且其所有边的权 ...

  7. HDU 1879 继续畅通工程 (Prim(普里姆算法)+Kruskal(克鲁斯卡尔))

    继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Sub ...

  8. 最小生成树-普利姆算法lazy实现

    算法描述 lazy普利姆算法的步骤: 1.从源点s出发,遍历它的邻接表s.Adj,将所有邻接的边(crossing edges)加入优先队列Q: 2.从Q出队最轻边,将此边加入MST. 3.考察此边的 ...

  9. 最小生成树-普利姆算法eager实现

    算法描述 在普利姆算法的lazy实现中,参考:普利姆算法的lazy实现 我们现在来考虑这样一个问题: 我们将所有的边都加入了优先队列,但事实上,我们真的需要所有的边吗? 我们再回到普利姆算法的lazy ...

随机推荐

  1. UIActivityIndicatorView

    1.    activityIndicatorViewStyle 设置指示器的样式 UIActivityIndicatorViewStyleWhiteLarge UIActivityIndicator ...

  2. HTML-移动端如何使用css让百分比布局的弹窗水平和垂直方向上居中

    pc端让一个弹窗水平和垂直方向居中,在知道弹窗宽高的情况下很好计算,只需要用如下css即可: #date{ width: 300px; height: 300px; position: absolut ...

  3. G面经prepare: Pattern Match

    设定一个pattern 把 'internationalization' 变成 'i18n', 比如word是house,pattern可以是h3e, 3se, 5, 1o1s1等, 给pattern ...

  4. hdu 2892 Area

    http://acm.hdu.edu.cn/showproblem.php?pid=2892 解题思路: 求多边形与圆的相交的面积是多少. 以圆心为顶点,将多边形划分为n个三角形. 接下来就求出每个三 ...

  5. 11.Java反射机制 哦对了,前面的序号来自随笔关于编程之路的思索第一篇

    基本概念 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法? 答案是肯定的. 这种动态获取类的信息以及动态调用对象的方法的功能来自于J ...

  6. CSSの神小结-简单备忘一下(亲测可用)

    css 选择器优先级,标签>id>class 权重 id>class>标签 只记录能想到的以免遗忘: 1.字体css可继承 2.表格:表格细线的合并,表格单元格合并,单元格内容 ...

  7. 初级node+express建站

    我的建站经历. 我建站的原因也很简单,就仅仅想有一个linux服务器玩一玩,但是还没有想到要怎么玩,就先搭建一个web服务吧.因为我工作的时候可能会用到. 我就从头开始讲起走. 先买了个云服务器,选择 ...

  8. Web服务器处理HTTP压缩之gzip、deflate压缩

    现如今在处理http请求的时候,由于请求的资源较多,如果不启用压缩的话,那么页面请求的流量将会非常大.启用gzip压缩,在一定程度上会大大的提高页面性能.   目录 一.什么是gzip 二.什么是de ...

  9. 实施费用也能DIY--走出软件作坊:三五个人十来条枪 如何成为开发正规军(九)[转]

    上次咱们讲完了开发费用的计算,很多人在后面跟帖在那里算费用. 有人说:你把程序员都不当人,94天,一天都不休息啊. 我想答曰:94天,是工作时间.不算双休日在里面.也就是说,实际的开发周期长度是94+ ...

  10. asp.net中获得客户端的IP地址

    asp.net中获得客户端的IP地址 因为要在项目中取到客户端IP,在网上搜了下相关资料,其中有一篇文章总结的比较详细,这里就把一些我用的上总结一下 方便以后查阅.  通常我们都通过下面的代码获得IP ...