天下大事,必做于细;天下难事,必作于易。
这个算法看了两天,边看边骂那一种,可今天,我先把并查集算法的代码搞懂了,结果才发现不过是排序后的元素进行并查集操作。
具体思想:将图的每条边保存下来(a:顶点,b:顶点,w:权重),a<b;
然后将按照权重大小进行边排序,(冒泡,快排,还未学到排序,所以我用的最简单的冒泡),然后将边进行合并。
具体代码如下:
// day19.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<iostream>
using namespace std;
typedef struct road
{
int a,b;
int w;
}road;
typedef struct
{
int n,e;
int data[100][100];
}graph;
void createg(graph &g)
{
int i,row,column,weigt;
cout<<"请输入顶点个数,边的条数"<<endl;
cin>>g.n>>g.e;
for(i=0;i<g.e;i++)
{
cout<<"请输入边的顶点,权值"<<endl;
cin>>row>>column>>weigt;
g.data[row][column]=weigt;
g.data[column][row]=weigt;
}
}
road r[100];
void createroad(graph g,road r[])
{
int i,j,num=0;
for(i=0;i<g.n;i++)
{
for(j=0;j<g.n;j++)
{
if(g.data[i][j]!=0&&i<j)
{
r[num].a=i;
r[num].b=j;
r[num].w=g.data[i][j];
num++;
}
}
}
for(i=0;i<num-1;i++)
{
for(j=0;j<num-1-i;j++)
{
road a;
if(r[j].w>r[j+1].w)
{
a=r[j];
r[j]=r[j+1];
r[j+1]=a;
}
}
}
}
int getroot(int a,int pre[])
{
while(a!=pre[a])
{
a=pre[a];
}
return a;
}
void kruskal(road r[],graph g)
{
int i,root1,root2,sum=0;
int pre[100]={0};
for(i=0;i<g.n;i++)
{
pre[i]=i;
}
// for(i=0;i<g.e;i++)
// {
// cout<<r[i].a<<' '<<r[i].b<<' '<<r[i].w<<endl;
// }
for(i=0;i<g.e;i++)
{
root1=getroot(r[i].a,pre);
root2=getroot(r[i].b,pre);
cout<<root1<<' '<<root2<<endl;
if(root1!=root2)
{
pre[root1]=root2;
sum+=r[i].w;
}
}
for(i=0;i<g.n;i++)
cout<<pre[i]<<' ';
cout<<"最小权值"<<sum<<endl;
}
int main(int argc, char* argv[])
{
road r[100];
graph g;
createg(g);
createroad(g,r);
kruskal(r,g);
return 0;
}