最小生成树是指一个图,然后怎么能够让它连通起来并且所有的边的权重加起来最短,是一个全局的作用,要用到并查集,并查集是一个“分帮结派”的过程,重点是father数组、find函数和join函数,一个图,每两个点之间有一条线,则这两个点就是一家的,有共同的根节点,其中一个为另一个的father,在寻找的过程中,一个家族的点,father可能不一样,但是find(x)的值肯定是一样的,为根节点,当然这个是随机的。点为核心。
最小生成树是以边(edge)为核心,先建一个结构体,包括起点、终点和权重。录入的过程就是标记的过程,记录下来这个边的起点、终点、权重。
然后在加入并查集的过程中各个边是有优先级的,因为想要最小生成树,所以保证加入的边的权是可以选择的最小的,所以先来一个cmp排序,然后再从第一条边开始扫起。
第一条边肯定要加进去的,然后看第二小的,如果此条边的两个点在一个集合中,加进去就是回路了,如果不在,加进去刚好可以联通,所以kruskal算法的思路就出来了。
poj的highways是最基础的最小生成树的题,但是还是想放上我们自己oj的题~
#include<iostream>
using namespace std;
#include<algorithm>
const int maxn = 105;
int n;//n个城市
int V, E;//V个点,E条边
struct edge
{
int u, v, cost;
};
edge eg[maxn*maxn];
int father[maxn];
void setfather(int n)
{
for (int i = 0; i < n; i++)
father[i] = i;
}
int find(int x)
{
while (father[x] != x)
x = father[x];
return x;
}
void join(int x, int y)
{
int fx = find(x);
int fy = find(y);
if (fx != fy)
father[fx] = fy;
}
bool cmp(const edge &a, const edge &b)
{
return a.cost < b.cost;
}
void kruskal()
{
setfather(n);
sort(eg, eg + n*n,cmp);
int Max = -1;
int sum = 0;
for (int i = 0; i < E; i++)
{
edge e = eg[i];
if (find(e.u) != find(e.v))
{
join(e.u, e.v);
Max = max(Max, e.cost);
sum = sum + e.cost;
}
}
cout << sum << endl;
}
int main()
{
while (cin>>n)
{
int cnt = 0;
int i, j;
for(i=0;i<n;i++)
for (j = 0; j < n; j++)
{
eg[cnt].u = i;
eg[cnt].v = j;
cin >> eg[cnt].cost;
cnt++;
}
V = n;
E = n*n;
kruskal();
}
return 0;
}
大家一起富起来
时间限制: 1000ms 内存限制: 128M
描述
为了促进山区乡镇的发展,政府决定在山区修建道路。由于在山区修路的成本极高,因此修建道路总长越短越好,但是必须保证任意两个乡镇互相通达。
输入
输入:输入有多组,每组的第一行是一个整数N(3<=N<=100),表示乡镇总数。接下来有N行输入,每行N个数,每i行的第j个数表示村庄i和j的距离(距离在[1,1000]区间内)。
输出
对于每组数据,输出需要修建的最短道路长度。
样例输入1
3
0 990 692
990 0 179
692 179 0
样例输出1
871