数据结构实验之图论九:最小生成树
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的。现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市。
Input
输入包含多组数据,格式如下。
第一行包括两个整数n m,代表城市个数和可以修建的公路个数。(n <= 100, m <=10000)
剩下m行每行3个正整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c。
Output
每组输出占一行,仅输出最小花费。
Sample Input
3 2
1 2 1
1 3 1
1 0
Sample Output
2
0
Hint
所谓最小生成树就是有n-1条边,且不能构成回路的图结构。
解题思路是首先根据权值从小到大排序(结构体的快排),然后用到并查集的知识,判断是否拥有一个首领,然后进行一波骚操作,输出即可。
代码如下:
#include <stdio.h>
#include <stdlib.h>
int f[100010];
int n;
struct node
{
int u;
int v;
int w;
}str[100010],key;
void sqort(int l, int r)
{
int j, i;
i = l;
j = r;
key = str[l];
if(l >= r)
return;
while(i < j)
{
while(i < j&&str[j].w >= key.w)
{
j--;
}
str[i] = str[j];
while(i < j&&str[i].w<= key.w)
{
i++;
}
str[j] = str[i];
}
str[i] = key;
sqort(l,i-1);
sqort(i+1,r);
}
void init() //初始化将每一个的首领都设为本身
{
int i;
for(i = 1;i <= 100010;i++)
{
f[i] = i;
}
}
int getf(int u) //返回首领
{
if(f[u] == u) //如果是本身单独一个,首领就是本身
return u;
f[u] = getf(f[u]); //反之就会递归到上一级,这用到路径压缩的知识
return f[u];
}
int merge(int u, int v) //这个函数是将前面求到的首领都连起来
{
int t1,t2;
t1 = getf(u);
t2 = getf(v);
if(t1 != t2)
{
f[t1] = t2;
return 0;
}
return 1;
}
int main()
{
int m, sum, num, i;
while(~scanf("%d %d",&n, &m))
{
init();
//sum = 0;
for(i = 0;i < m;i++)
{
scanf("%d %d %d",&str[i].u,&str[i].v,&str[i].w);
}
sqort(0,m-1);
num = sum = 0;
for(i = 0;i < m;i++)
{
if(num == n-1) //如果找的边已经够 n-1 条就退出
break;
if(merge(str[i].u,str[i].v) == 0)//根据返回值应该返回0的时候
{
num++;
sum += str[i].w;
}
}
printf("%d\n",sum);
}
return 0;
}