这个算法结合并查集,相较于另一个算法而言,这个相对于我来说理解起来更加容易。
就上面的图来说,假如说1/2/3/4/5/6分别代表不同的商店,这些商店我都要过去,而我去这些商店的时候,又需要不同的车费,让求怎么走才能使得车费少。
这个就是最小生成树所要解决的问题,选择最少的车费。
1、将车费从小到大排序,然后我们的选择顺序就是这个顺序
2、运用并查集的思想(先判断两点是否能够构成环或者说有没有共同的祖先,如果有的话就过,反之,就把这条路计算到里面,然后让走过的边的数量加一,如果边的数量等于商店数量减一就结束)
#include<stdio.h>
#include<algorithm>
using namespace std;
struct xiao
{
int u,v,w;
}a[100];
int father[100];
void quicksort(int x,int y)
{
//分别代表的是左端点和右端点
struct xiao t;
int left=x;
int right=y;
if(left>right) return ;
int index=a[left].w;
while(left!=right)//现在需要知道的是一个已经排完序的情况
{
while(a[right].w>=index&&left<right)
{
right--;
}
while(a[left].w<=index&&left<right)
{
left++;
}
if(left<right)
{
t=a[left];
a[left]=a[right];
a[right]=t;
}
}
//最终将基准数归位。
t=a[x];
a[x]=a[left];
a[left]=t;
quicksort(x,left-1);
quicksort(left+1,y);
return ;
}
int Find(int x)
{
if(x!=father[x])
{
father[x]=Find(father[x]);
}
return father[x];
}
int combine(int x,int y)
{
int fx=Find(x);
int fy=Find(y);
if(fx!=fy)
{
father[fx]=fy;
return 1;
}
return 0;
}
int main()
{
int n,m,number=0,outputs=0;//n个点,m条路
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
for(int i=1;i<=n;++i)
father[i]=i;
quicksort(1,m);
//已经排好序了!
// for(int i=1;i<=m;++i)
// printf("%d\n",a[i].w);
for(int i=1;i<=m;++i)
{
if(combine(a[i].u,a[i].v))
{
++number;
outputs+=a[i].w;
}
if(number==n-1)
break;
}
printf("%d\n",outputs);
return 0;
}
//6 9
//2 4 11
//3 5 13
//4 6 3
//5 6 4
//2 3 6
//4 5 7
//1 2 1
//3 4 9
//1 3 2