电网建造造价:最小生成树问题(prime算法)

对原本的prime算法进行了改进,原本的算法好像只能输入生成的最小生成树的路径长度(权值和),为了满足题目要求,新建了一个结构体用来存储寻找最短距离过程中更新过的最短距离,并在树的生成过程中保存结构体数组中的数据。(方法不太巧妙,但总算是满足了要求)详细过程已注释。

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
struct link
{
    int sta,stop,weight;
}bian[1000];
struct link2
{
    int u,weight;
}bian2[1000];
link li[100];
const int maxv=1000;
const int INF=10000000;
int n,m,G[maxv][maxv];
int d[maxv];
bool vis[maxv]={false};
int num=0;
int prime(int &num)//&引用,在函数内改变全局变量的值
{
    fill(d,d+maxv,INF);
    d[0]=0;//初始化0为出发点(任意)
    int ans=0;
    for(int i=0;i<n;i++)
    {
        int u=-1,min=INF;
        for(int j=0;j<n;j++)
        {
            if(vis[j]==false&&d[j]<min){
                u=j;
                min=d[j];
            }
        }//找出当前离“集合”最短的点
        if(u==-1)
            return -1;
        vis[u]=true;//设置已访问
        ans+=d[u];//找到后加入生成树中
        //使用一个新的link数组来保存生成树过程中所加入的路径
        li[num].sta=bian2[u].u;//u代表这点路的终点
        li[num].stop=u;
        li[num].weight=bian2[u].weight;
        num++;
        for(int v=0;v<n;v++)
        {
            if(vis[v]==false&&G[u][v]!=INF&&G[u][v]<d[v]){
                //以找出的最短点为起点更新,
                //寻找可以更新与“集合”最短的点(且未被访问过)
                d[v]=G[u][v];//更新最短距离,并保存入数组中
                bian2[v].u=u;//bian2用来保存生成树的路径
                bian2[v].weight=d[v];
            }

        }
    }
    return ans;
}
void print(link a)
{
    cout<<" ("<<a.sta<<","<<a.stop<<","<<a.weight<<") ";
}
bool cp1(link a,link b)
{
    return a.weight<b.weight;
}
int main()
{
    int i,j,k,a,b,c;//不可再对n,m重新定义,不然全局变量失效
    fill(G[0],G[0]+maxv*maxv,INF);
    cout<<"请输入顶点个数和边数"<<endl;
    cin>>n>>m;
    cout<<"请输入"<<m/2<<"个边的起点、终点、权值"<<endl;
    for(i=0;i<m/2;i++)
    {
        cin>>a>>b>>c;
        bian[i].sta=a;
        bian[i].stop=b;
        bian[i].weight=c;
        G[a][b]=c;
        G[b][a]=c;
    }
    int ans=prime(num);
    cout<<"输出边集数组中的每条边"<<endl;
    for(i=0;i<m/2;i++)
    {
        print(bian[i]);
    }
    sort(bian,bian+m/2,cp1);//以路径长度为标准进行排序
    cout<<"输出按升序排列的图的边集数组:"<<endl;
     for(i=0;i<m/2;i++)
    {
        print(bian[i]);
    }
    cout<<endl;
    cout<<"最短路径长度:"<<ans<<endl;
    cout<<"输出最小生成树的边集数组:"<<endl;
    for(i=1;i<num;i++)//第一个数据为空
        print(li[i]);
    return 0;
}
阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页