图论小结(最小生成树)

最小生成树是指一个图,然后怎么能够让它连通起来并且所有的边的权重加起来最短,是一个全局的作用,要用到并查集,并查集是一个“分帮结派”的过程,重点是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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值