Prim和Kruskal 留给自己看的 备份用写的一般 莫喷

都用并查集了,这玩意是真的好用

#include<iostream>
using namespace std;

const int MAX = 0xfffff;//default maximum cost
int G[10][10] = {
	//0, 1,  2,  3,  4,  5,  6,  7,  8,	  9
	{MAX,4,  MAX,MAX,MAX,MAX,MAX,8,  MAX, MAX},//0
	{4,  MAX,8,  MAX,MAX,MAX,MAX,3 , MAX, MAX},//1
	{MAX,8,  MAX,7,  MAX,4,  MAX,MAX,2  , MAX},//2
	{MAX,MAX,7  ,MAX,9,  14, MAX,MAX,MAX, MAX},//3
	{MAX,MAX,MAX,9,  MAX,10, MAX,MAX,MAX, MAX},//4
	{MAX,MAX,4,  14, 10 ,MAX,2,  MAX,MAX, MAX},//5
	{MAX,MAX,MAX,MAX,MAX,2,  MAX,6,  6  , MAX},//6
	{8  ,3  ,MAX,MAX,MAX,MAX,6  ,MAX,1  , MAX},//7
	{MAX,MAX,2,  MAX,MAX,MAX,6  ,1  ,MAX, 0},//8
	{MAX,MAX,MAX,MAX,MAX,MAX,MAX,MAX,MAX,MAX},//9
};

typedef struct Edge{
	int i,j,e;//The directed edge from i to j,and the cost is e.
}Edge;

Edge tree[100];//10 vertices up to 100 edges
int top = 0;//The number of valid edges

void Matrix2Edge()
{
	for(int i = 0;i<10;i++)
		for(int j = i+1;j<10;j++)
		{
			if(G[i][j]!=MAX)
			{
				tree[top].i = i;
				tree[top].j = j;
				tree[top].e = G[i][j];
			}
			top++;
		}
}
//Part of union and set
int unin[10];
void init()
{
	for(int i = 0; i<10;i++)
		unin[i]=i;
}
int Find(int x)
{
	while(unin[x]!=x)
		x=unin[x];
	return x;
}
void Union(int x,int y)
{//merge y to the union where x is in
	int xx = Find(x),yy=Find(y);
	unin[yy]=xx;
}
bool isTHESAME(int x, int y)
{
	return Find(x)==Find(y);
}

//FastSort
void FastSort(Edge *arr, int left,int right)
{
	if(left>=right)
		return;
	Edge temp = arr[left];
	int a=left,b=right;
	while(a<b)//'a==b'while loop exits
	{
		while(a<b&&arr[b].e>=temp.e)
			b--;
		arr[a]=arr[b];
		while(a<b&&arr[a].e<=temp.e)
			a++;
		arr[b]=arr[a];
	}
	arr[a]=temp;
	FastSort(arr,left,a-1);
	FastSort(arr,a+1,right);
}
Edge t[9];//Get ready for Kruskal return-values
void Kruskal()
{
	int k = 0;//A tree consists of 9 edges
	
	Matrix2Edge();
	FastSort(tree,0,top-1);
	init();
	for(int i = 0;i<top;i++)
	{
		if(isTHESAME(tree[i].i,tree[i].j))
			continue;
		Union(tree[i].i,tree[i].j);
		t[k++]=tree[i];
		if(k==9)
			return;
	}
}

//Prim()算法笔记(伪代码)
//1、创建一个并查集,用于检验是否成环。开始时,假设v={0}。即:0是并查集中唯一的成员。
//2、创建一个队列,用于保存部分生成树中与顶点相邻的所有边
//3、创建数组t,作为边集,用于保存生成树
//4、算法开始,直到有n-1个边添加到树里边。使用变量k来记录已添加的边的数量,初始时k=0
//	4.1、从并查集中取出一个"还未添加所有边的元素"
//	4.2、将他所有连接的边添加到队列
//	4.3、剔除队列中所有成环的边,最后剩下的边,他的始点(Edge::i)一定在并查集中,他的终点(Edge::j)一定不在并查集中。
//	4.4、将边快速排序
//	4.5、取出最小边e,加入到边集t
//	4.6、将e.j添加到并查集中,并将e.j视为"还未添加所有边的元素"
//	4.7、k++
void Prim(int source = 0)
{//defalut source point = 0
	init();//Initiate union and set.
	int head = 0,tail = 0,temp;
	int k = 0,j=0;//the number of created tree's edges
	int Root = source;//Use UST to reserve tree
	while(k!=9)
	{
		for(int i = 0;i<10;i++)
			if(G[source][i]!=MAX)
			{//Contains all edge around reserved point
				tree[tail].e=G[source][i];
				tree[tail].i = source;
				tree[tail].j = i;
				tail=(tail+1)%100;
			}
		temp = tail;//reserve tail-value
		for(int i = head;i<temp;i=(i+1)%100)
		{//Remove LOOP-MAKER!
			j=tree[i].j;//the head of the queue, and i must be in! Thus i neednt to be affirmed.
			if(!isTHESAME(Root,j))
			{//if this edge isnt LOOP-MAKER
				tree[tail]=tree[i];//add it to queue
				tail=(tail+1)%100;
			}
		}
		head = temp;//omit old edge
		FastSort(tree,head,tail-1);
		t[k] = tree[head];//take the minimum edge
		head = (head+1)%100;
		j = t[k].j;
		Union(Root,j);//Welcome to our tree.point!
		source = j;//update source
		k++;//tree.point.ok++!
	}
}
int main()
{
	int cost = 0;
	cout<<"Kruskal algorithm functioning...\n";
	Kruskal();
	for(int i =0;i<9;i++)
	{
		cout<<t[i].i<<"----"<<t[i].j<<", Cost = "<<t[i].e<<endl;
		cost+=t[i].e;
	}
	cout<<"The minimum cost is: "<<cost<<endl;

	cost = 0;
	cout<<"Prim algorithm functioning...\n";
	Prim();
	for(int i =0;i<9;i++)
	{
		cout<<t[i].i<<"----"<<t[i].j<<", Cost = "<<t[i].e<<endl;
		cost+=t[i].e;
	}
	cout<<"The minimum cost is: "<<cost<<endl;

	system("pause");
	return 16; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值