最小生成树

最小生成树有两种算法,一种是克鲁斯卡尔(Kruskal)算法。

这种算法只与边相关,所以在定义数组的时候定义一个结构体

struct list
{
    int x;//边的一个点
    int y;//边的另一个点
    int l;//边的权值
}s[500];//存储边
1.先对所有的边按照权值排序。

2.找到最小的那个边,查看边的两点是不是都找到了,如果不是,继续下一步。

对于这个地方,需要使用到并查集,把所有的已经找到的点放在一个并查集里面,然后直接判断这个边的两个点的值是不是一样就可以了。

int get(int x)
{
    while(f[x]!=x)
        x=f[x];
    return x;
}
int find(int x,int y)
{
    x=get(x);
    y=get(y);
    if(x==y)return 0;
    f[y]=x;
    return 1;
}

3.继续第二步,直到找到最小生成树。

hdu 1233

#include<stdio.h>
#include<stdlib.h>
struct list
{
    int x,y;
    int l;
}s[10000];
int f[1002];
int cmp(const void *a,const void *b)
{
    return (*(struct list *)a).l>(*(struct list *)b).l?1:-1;
}
int get(int x)
{
    while(f[x]!=x)
        x=f[x];
    return x;
}
int find(int x,int y)
{
    x=get(x);
    y=get(y);
    if(x==y)return 0;
    f[y]=x;
    return 1;
}
int main()
{
    int n,i,m;
    while(scanf("%d",&n)&&n)
    {
        for(i=1;i<=n;i++)
        f[i]=i;
        m=n*(n-1)/2;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&s[i].x,&s[i].y,&s[i].l);
        }
        qsort(s,m,sizeof(s[0]),cmp);
        long long sum=0;
        int leap=1;
        for(i=0;i<m;i++)
        {
            if(find(s[i].x,s[i].y))
            {
                sum+=s[i].l;leap++;
                if(leap==n)break;
            }
        }
        printf("%lld\n",sum);
    }
    return 0;
}
二:普利姆(Prime)算法

这个算法主要是与点有关系。所以定义数组的时候定义map[][];

算法过程:

1.先随便选一个点i,定义一个low数组,存储点i到其它点的距离。定义一个visit数组,判断是否被访问过。

2.寻找low数组中的最小数,然后搜寻一遍这个数到其他点的距离是不是小于low数组,如果小于,就更新low数组。

3.循环2步骤,直至找到最小数。

hdu 1233

#include<stdio.h>
#include<string.h>
#define INF 0x3f3f3f3f
int main()
{
    int n,a,b,c;
    int map[102][102];
    while(scanf("%d",&n)&&n)
    {
        int m,i;
        m=n*(n-1)/2;
        memset(map,0,sizeof(map));
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            map[a][b]=c;
            map[b][a]=c;
        }
        int visit[102],low[102],min,leap,j;
        memset(visit,0,sizeof(visit));
        visit[1]=1;
        for(i=1;i<=n;i++)
            low[i]=map[1][i];
        int sum=0;
        for(i=1;i<=n;i++)
        {
            min=INF;
            for(j=1;j<=n;j++)
            {
                if(visit[j]==0&&min>low[j])
                {
                    min=low[j];leap=j;
                }
            }
            if(min==INF)break;
            sum+=min;
            visit[leap]=1;
            for(j=1;j<=n;j++)
            {
                if(low[j]>map[leap][j])
                    low[j]=map[leap][j];
            }
        }
        printf("%d\n",sum);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值