都用并查集了,这玩意是真的好用
#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;
}