您的位置:首页 > 其它

图结构练习——最小生成树

2016-05-14 23:10 369 查看
图结构练习——最小生成树

Time Limit: 1000MS Memory limit: 65536K

题目描述

 有n个城市,其中有些城市之间可以修建公路,修建不同的公路费用是不同的。现在我们想知道,最少花多少钱修公路可以将所有的城市连在一起,使在任意一城市出发,可以到达其他任意的城市。

 

输入

 输入包含多组数据,格式如下。

第一行包括两个整数n m,代表城市个数和可以修建的公路个数。(n <= 100, m <=10000)

剩下m行每行3个正整数a b c,代表城市a 和城市b之间可以修建一条公路,代价为c。

 

输出

 每组输出占一行,仅输出最小花费。

示例输入

3 2 1 2 1 1 3 1 1 0

示例输出

2 0

提示

 

#include

#include

#include

#define MAX_N 120

#define MAX_A 0x3f3f3f3f

int map[MAX_N][MAX_N],low[MAX_N],visit[MAX_N];

int n;

int prim()

{

    int  i,j,pos,min,result = 0;

    memset(visit,0,sizeof(visit));

    visit[1] = 1;

    pos = 1;

    for(i = 2; i <= n; i++)

    {

        low[i] = map[pos][i];

    }

    for(i = 1; i < n; i++)

    {

        min =MAX_A;

        for(j = 1; j <= n; j++)

        {

            if(visit[j] == 0 && min > low[j])

            {

                min = low[j];

                pos = j;

            }

        }

        result = result + min;

        visit[pos] = 1;

        for(j = 1; j <= n; j++)

        {

            if(visit[j] == 0 && low[j] > map[pos][j])

                low[j] = map[pos][j];

        }

    }

    return result;

}

int main()

{

    int m,i,j;

    int a,b,c;

    while(~scanf("%d %d",&n,&m))

    {

        for(i = 1; i <= n; i++)

        {

            for(j = 1; j <= n; j++)

            {

                map[i][j] = MAX_A;

            }

        }

        for(int k = 0; k < m; k++)

        {

            scanf("%d %d %d",&a,&b,&c);

            if(map[a][b]>c)

            {

                map[a][b] = c;

                map[b][a] = c;

            }

        }

        printf("%d\n",prim());

    }

    return 0;

}

 这题是最小生成树的问题,,关于最小生成树有几种算法

求MST的一般算法可描述为:针对图G,从空树T开始,往集合T中逐条选择并加入n-1条安全边(u,v),最终生成一棵含n-1条边的MST。
当一条边(u,v)加入T时,必须保证T∪{(u,v)}仍是MST的子集,我们将这样的边称为T的安全边。

Prim算法简述

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

2).初始化:Vnew= {x},其中x为集合V中的任一节点(起始点),Enew= {},为空;

3).重复下列操作,直到Vnew= V:

a.在集合E中选取权值最小的边,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);

b.将v加入集合Vnew中,将边加入集合Enew中;
4).输出:使用集合Vnew和Enew来描述所得到的最小生成树。[1] 

Kruskal算法简述

假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。[1] 

代码菜鸟,如有错误,请多包涵

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: