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

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

#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;
}