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

图结构练习——最小生成树
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] 
代码菜鸟,如有错误,请多包涵
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值