【无标题】

生成树:

所有顶点均由边连接在一起,但不存在回路的图

一个图可以有多颗不同的生成树

含有n个顶点n-1条边的图不一定是生成树

所有生成树具有以下特点:

1.生成树的顶点个数与图的顶点个数相同

2.生成树是图的极小连通子图,去掉一条边则非连通

3.一个有n个顶点的连通图的生成树有n-1条边

4.在生成树中再加一条边必然形成回路

5.生成树中任意两个顶点间的路径是为宜的

生成树有很多种算法实现,比如常用的深度优先搜索(DFS)和广度优先搜索(BFS)等。

最小生成树:

给定一个无相网络,在该网的所有生成树中,使得各边权值之和最小的那颗生成树成为该网的最小生成树,也叫最小代价树。

MST性质:设N=(V,E)是一个;联通网,U是顶点集V的一个非空子集。若边(u,v)是一条具有最小权值的边,其中u属于U,v属于V-U,则必然存在一颗包含(u,v)的最小生成树。

 

在构造生成树中,图中n个顶点分属两个集合:

1.已落到生成树上的顶点集:U

2.尚未落到生成树上的顶点集:V-U

然后就在U中顶点和V-U中顶点的边中选权值最小的边。

普里姆算法:

 

#include "stdio.h"
#include "stdlib.h"
#include "limits.h"


int n;

void prim(int graph[n][n]);

int min_d(int key [], int mark []);

int main()
{
	scanf("%d",&n);  //输入邻接矩阵的大小
	
	int graph[n][n];
	
	for(int i = 0 ; i < n ; i++)
		for(int j = 0 ; j < n ; j++)
	        scanf("%d",graph[i]+j);
	
	
	prim(graph);
	
}

//返回未标记顶点中距离离根最近的下标
int min_d(int key [], int mark [])
{
	int min=INT_MAX,xiabiao;
	
	for(int i = 0 ; i < n; i++)
	    if(mark[i] == 0 && key[i] < min)
	        min = key[i] , xiabiao = i;
	
	return xiabiao;
}

//普里姆生成最小树
void prim(int graph[n][n])
{
	int parent[n];//最小生成树中每个顶点的父节点
	int key[n];  //存贮每个顶点与当前最小生成树之间的最短边权值
	int mark[n]; //每个顶点是否包含在最小生成树中
	
	
	for(int i = 0 ; i < n ; i++)
	key[i]=INT_MAX,mark[i]=0;
	
	key[0]=0;
	
	
	for(int count = 0 ; count < n-1; count++)
	{
		int u = min_d(key , mark);
		
		mark[u] = 1;
		
		for (int v = 0; v < n; v++)
		if (graph[u][v] && mark[v] == 0 && graph[u][v] < key[v])
		    parent[v] = u, key[v] = graph[u][v];
		    
	}
	
	// 打印生成的最小生成树
	void printMST(int parent[], int graph[n][n])
	{
	    printf("Edge \tWeight\n");
	    for (int i = 1; i < n; i++)
	        printf("%d - %d \t%d \n", parent[i], i, graph[i][parent[i]]);
	}
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值