问题 A: DS图—最小生成树

问题 A: DS图—最小生成树

题目描述

根据输入创建无向网。分别用Prim算法和Kruskal算法构建最小生成树。(假设:输入数据的最小生成树唯一。)

输入

顶点数n

n个顶点

边数m

m条边信息,格式为:顶点1 顶点2 权值

Prim算法的起点v

输出

输出最小生成树的权值之和

对两种算法,按树的生长顺序,输出边信息(Kruskal中边顶点按数组序号升序输出)

样例输入

6
v1 v2 v3 v4 v5 v6
10
v1 v2 6
v1 v3 1
v1 v4 5
v2 v3 5
v2 v5 3
v3 v4 5
v3 v5 6
v3 v6 4
v4 v6 2
v5 v6 6
v1

样例输出

15
prim:
v1 v3 1
v3 v6 4
v6 v4 2
v3 v2 5
v2 v5 3
kruskal:
v1 v3 1
v4 v6 2
v2 v5 3
v3 v6 4
v2 v3 5

代码

#include <iostream>
#include <string>
#include <algorithm>
#define INFINITY 999999
using namespace std;

struct Edge
{
    
    
    int start,end,weight;
};

class Graph//没有使用动态数组,待优化
{
    
    
public:
    int vexnum;
    int edge;
    int adjMatrix[20][20];//邻接矩阵
    int begin;
    string name[20];//结点信息
    int value;
    Edge edgeset[100];
    int father[100]; //并查集
public:
    void initial()
    {
    
    
        value=0;
        cin >> vexnum;
        for(int i=0;i<vexnum;i++){
    
    
            cin >> name[i];
        }
        for(int i=0;i<20;i++)
            for(int j=0;j<20;j++)
                adjMatrix[i][j]=INFINITY;
        cin >> edge;
        for(int i=0;i<edge;i++){
    
    
            string t1,t2;
            int weight;
            cin >> t1 >> t2 >> weight;
            int a1,a2;
            a1=find_index(t1);
            a2=find_index(t2);
            adjMatrix[a1][a2]=weight;
            adjMatrix[a2][a1]=weight;//无向图
            edgeset[i].start=a1;//初始化边数组
            edgeset[i].end=a2;
            edgeset[i].weight=weight;
        }
        string begin1;
        cin >> begin1;
        begin=find_index(begin1);
    }
    int find_index(string a)
    {
    
    
        for(int i=0;i<vexnum;i++)
            if(!a.compare(name[i]))return i;
    }
    void Prim()/*n^2*/
    {
    
    
        int array[100]={
    
    0};
        int array1[100]={
    
    0};
        Edge *close_edge=new Edge[vexnum];
        for(int i=0;i<vexnum;i++){
    
    //对于所有的结点,初始化closeedge上原点到他们的距离      /*频度为n*/
            if(i!=begin){
    
    
                close_edge[i].start=begin;
                close_edge[i].end=i;
                close_edge[i].weight=adjMatrix[begin][i];
            }
        }
        close_edge[begin].weight=-1;//表示原点已经加入U了
        //然后访问剩下的顶点,依次加入U
        for(int i=1;i<vexnum;i++){
    
                                                         /*n-1*/                                                 
            //1.寻找close_edge中权重最小的边
            int min=INFINITY,index;//index对应结点下标
            for(int j=0;j<vexnum;j++){
    
                                                    /*频度为n-1*/
                if(close_edge[j].weight!=-1&&close_edge[j].weight<min){
    
    
                    min=close_edge[j].weight;
                    index=j;
                }
            }
            array[i]=index;
            array1[i]=close_edge[index].weight;
            value+=min;//权值
            //2.将其加入集合U
            close_edge[index].weight=-1;
            //3.更新close_edge数组
            for(int j=0;j<vexnum;j++){
    
    //更新距离//优化名称                               /*频度为n*/
                if(adjMatrix[close_edge[index].end][j]<close_edge[j].weight){
    
    //如果index到j的距离小于j的close_edge距离
                    close_edge[j].weight=adjMatrix[close_edge[index].end][j];
                    close_edge[j].start=close_edge[index].end;
                    close_edge[j].end=j;
                }
            }
        }
        cout << value << endl;
        cout<<"prim:"<<endl;
        for(int i=1;i<=vexnum-1;i++){
    
    
            cout << name[close_edge[array[i]].start] << ' ' << name[close_edge[array[i]].end] << ' ' << array1[i] << endl;
        }
    }
    int find(int pos)
    {
    
    
        if(father[pos]!=pos)return find(father[pos]);
        else return pos;
    }
    void sort(Edge data[], int n)
    {
    
    
        for(int i=n-1;i>=1;i--){
    
    
            for(int j=1;j<=i;j++){
    
    
                if(data[j-1].weight>data[j].weight){
    
    
                    Edge temp=data[j-1];
                    data[j-1]=data[j];
                    data[j]=temp;
                }
            }
        } 
    }
    void Kruskal()
    {
    
    
        cout<<"kruskal:"<<endl;
        for(int i=0;i<vexnum;i++)//结点之间在farther里顺序排列
            father[i] = i;
        sort(edgeset,edge);
        /*从E中找到代价最小的边,且该边两点在不同的两个连通分量上*/
        int k=0;//边数
        for(int i=0;i<edge;i++){
    
    
            if(k>=vexnum-1)break;
            int a1,a2;
            a1=find(edgeset[i].start);
            a2=find(edgeset[i].end);
            if(a1!=a2){
    
    //这条边ok
                father[a1]=a2;//合并并查集
                k++;//有效边多了
                cout << name[edgeset[i].start] << ' ' << name[edgeset[i].end] << ' ' << edgeset[i].weight << endl;
            }
        }
    }
};

int main()
{
    
    
    Graph graph;
    graph.initial();
    graph.Prim();
    graph.Kruskal();
    return 0;
}

目的

一个笔记

猜你喜欢

转载自blog.csdn.net/NP_hard/article/details/110103568