求最小生成树两种算法

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ancientear/article/details/84781506

求最小生成树,两种算法,求输出权值的和。第一行n,m,n为顶点数,小于等于20,m边数,后面m行,每行一个边的信息,每行三个数,i j c,起点i,终点j,权值c,i,j大于等于1,无向图。

/*求最小生成树,,求输出权值的和。
 第一行n,m,n为顶点数,小于等于20,m边数,后面m行,每行一个边的信息,每行三个数
i j c,起点i,终点j,权值c,i,j大于等于1,无向图。*/

#include <iostream>
#include <cstring>
using namespace std;
#define mai 1001
int i,j,k;
int arr[mai][mai];
int prim(int arr[][mai],int n)//加点法
{
    //vis数组用来记录这个点是否已经加入最小生成树
    int vis[mai] = {0};
    
    //dis数组表示当前最小生成树(集体)的可以到达的非最小生成树的点的最小距离
    int dis[mai] = {0};
    
    memset(vis,0,sizeof(vis));
    int sum = 0,min = mai,number;
 
    for(i = 2;i <= n;i++)
        dis[i] = arr[1][i];//从1开始,dis数组初始化
        vis[1] = 1;
    
   //从第二次访问开始(并不是第二个点),控制一共访问n次,所有的点已访问
    for(i = 2;i <= n;i++)

    {
        min = mai;number = -1;//每次访问新点时重新赋值min
        for(j = 1;j <= n;j++)
        {
            if(vis[j] == 0 && dis[j] < min)
            {
                min = dis[j];
                number = j;//number记录当前最小权值的下标,方便vis标记
            }
        }
            //这个for执行完之后就可以找到dis数组里面的最小权值是min,对应的点是j
        sum += min;
      
        vis[number]=1;//将j点标记为已加入
        for(j = 1;j <= n;j++)
            if(vis[j] == 0 && arr[number][j] < dis[j])
                dis[j] = arr[number][j];
        
        
    }
    return sum;
    
    
}
int main()
{
    int n,m,i,j,c;
    cin >> n >> m;
    for(i = 0;i <= n;i++)
        for(j = 0;j <= n;j++)
            arr[i][j] = mai;
    for(i = 0;i < m;i++)
    {
        cin >> i >> j >> c;
        arr[i][j] = c;
        arr[j][i] = c;
    }
    int small = prim(arr,n);
    cout << small << endl;
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int cost[1020][1020];//cost[u][v]表示边e=(u,v)的权值(不存在的情况下设为INF)
int mincost[1020];//从集合X出发的边到每个顶点的最小权值
bool used[1020];//顶点i是否包含在集合X中
int prime();
int n,m,i,j,c;
int main()
{
    cin >> n >> m;
    memset(cost,INF,sizeof(cost));
    for(int i = 0;i < m;i++)
    {
        cin >> i >> j >> c;
        cost[i][j] = min(c,cost[i][j]);
        cost[j][i] = min(c,cost[j][i]);
    }
    cout<<prime()<<endl;
    return 0;
    
}

int prime()
{
    for(int i = 1;i <= n;i++)
    {
        mincost[i] = INF;
        used[i] = false;
    }
    mincost[1] = 0;
    int res = 0;
    while(true)
    {
        int v = -1;//从不属于X的顶点中选取从X到其权值最小的顶点
        for(int u=1;u <= n;u++)
        {
            if(!used[u] && (v == -1 || mincost[u] < mincost[v]))
                v = u;
        }
        if(v == -1)break;
        used[v] = true;//把顶点v加入X
        res += mincost[v];//把边的长度加到结果里
        for(int u = 1;u <= n;u++)
            mincost[u] = min(mincost[u],cost[v][u]);
    }
    return res;
}


猜你喜欢

转载自blog.csdn.net/ancientear/article/details/84781506
今日推荐