并查集实际上就是找"首领“的算法,可以分成几个团队,这个算法借助一个一维数组来实现,本质是维护一个森林。刚开始的时候,森林的每一个点都是孤立的,也可理解为每个点都是一棵只有一个节点的树。之后通过每个条件,逐渐将这些树合并成一棵大树。其中要遵守”靠左原则“和”擒贼先擒王“的原则,判断直到两个节点的祖宗一样才行。
数据结构实验之图论六:村村通公路
Problem Description
当前农村公路建设正如火如荼的展开,某乡镇政府决定实现村村通公路,工程师现有各个村落之间的原始道路统计数据表,表中列出了各村之间可以建设公路的若干条道路的成本,你的任务是根据给出的数据表,求使得每个村都有公路连通所需要的最低成本。
Input
连续多组数据输入,每组数据包括村落数目N(N <= 1000)和可供选择的道路数目M(M <= 3000),随后M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个村庄的编号和修建该道路的预算成本,村庄从1~N编号。
Output
输出使每个村庄都有公路连通所需要的最低成本,如果输入数据不能使所有村庄畅通,则输出-1,表示有些村庄之间没有路连通。
Sample Input
5 8 1 2 12 1 3 9 1 4 11 1 5 3 2 3 6 2 4 9 3 4 4 4 5 6
Sample Output
19
Hint
Source
xam
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
int u, v, w;
}str[100010], key;
int f[100010];
void sqort(int l, int r)
{
int i, j;
key = str[l];
i = l;
j = r;
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[t2] = t1;
return 0;
}
return 1;
}
int main()
{
int n, m, i, num, sum, flag;
while(~scanf("%d %d",&n,&m))
{
flag = 1;
init();
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)
{
flag = 0;
break;
}
if(merge(str[i].u,str[i].v) == 0)
{
num++;
sum += str[i].w;
}
}
if(flag == 0)
printf("%d\n",sum);
else printf("-1\n");
}
return 0;
}