DS图—最小生成树

题目描述

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

输入

顶点数n

n个顶点

边数m

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

Prim算法的起点v

输出

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

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

输入样例1输出样例1
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\n
prim:\n
v1 v3 1\n
v3 v6 4\n
v6 v4 2\n
v3 v2 5\n
v2 v5 3\n
kruskal:\n
v1 v3 1\n
v4 v6 2\n
v2 v5 3\n
v3 v6 4\n
v2 v3 5\n
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

struct line_message{
    int va,vb;
    int weight;

};
class min_tree{

    int t_v;
    string *v;
    int t_message;
    line_message *l;
    int **st;//邻接矩阵//其实没用到
    int prim_root;
    line_message *prim_tree,*kruskal_tree;
public:
    min_tree(){}
    min_tree(int t_v1,int t_m1,string *v1,line_message *l1,int root):t_v(t_v1),t_message(t_m1),prim_root(root){
        v = new string [t_v1];
        l = new line_message [t_m1];
        st = new int *[t_v];
        for(int i = 0 ; i < t_v ; i++ ){
            v[i] = v1[i];
            st[i] = new int [t_v];
            for(int j = 0 ; j < t_v ; j++){
                st[i][j] = 0;
            }
        }
        for(int i = 0 ; i < t_message ; i++ ){
            l[i].va = l1[i].va;l[i].vb = l1[i].vb;l[i].weight = l1[i].weight;
            for(int j = 0 ; j < t_v ; j++ ){
                for(int k = 0 ; k < t_v ; k++ ){
                    if(l[i].va == j&&l[i].vb == k){
                        st[j][k] = l[i].weight;
                    }
                }
            }
        }

    }
    void prim();
    void kruskal();
};
void min_tree::prim(){//prim2方法,非蛮力,所以会看着眼花

    int *tree_v = new int [t_v];
    for(int i = 0 ; i < t_v ; i++ ){
        tree_v[i] = 0;
    }
    tree_v[prim_root] = 1;
    prim_tree = new line_message[t_v-1];
    line_message *test = new line_message[t_message];
    for(int i = 0 ; i < t_message ; i++ ){
        test[i].va = l[i].va;
        test[i].vb = l[i].vb;
        test[i].weight = 10001;
        if(test[i].va==prim_root||test[i].vb==prim_root){
            test[i].weight = l[i].weight;
        }
    }
    int sum = 0;
    for(int j = 0 ; j <t_v-1 ; j++){
        int min = 999;int min_i =1000;
        for(int i = 0 ; i < t_message ; i++ ){
            if(test[i].weight!=0){
                if(test[i].weight < min&&(tree_v[test[i].va]==0||tree_v[test[i].vb]==0)){
                    min = test[i].weight;min_i = i;
                }
            }
        }
        if(tree_v[test[min_i].va]==0){
            swap(test[min_i].va,test[min_i].vb);
        }
        tree_v[test[min_i].va] =1;tree_v[test[min_i].vb] =1;
        prim_tree[j].va = test[min_i].va;
        prim_tree[j].vb = test[min_i].vb ;
        prim_tree[j].weight = test[min_i].weight;
        sum = sum + test[min_i].weight;
        test[min_i].weight = 0;//标记
        for(int i = 0 ; i < t_message ; i++ ){
            if(test[i].weight==10001&&(test[i].va==test[min_i].va||test[i].vb==test[min_i].va
            ||test[i].va == test[min_i].vb||test[i].vb == test[min_i].vb)){
                test[i].weight = l[i].weight;
            }
        }
    }
    cout<<sum<<endl<<"prim:"<<endl;
    for(int i = 0 ;i < t_v-1 ; i++ ){
        cout<<v[prim_tree[i].va]<<" "<<v[prim_tree[i].vb]<<" "<<prim_tree[i].weight<<endl;
    }

//    int *state = new int [t_v];
//    for(int i = 0 ; i < t_v ; i++ ){
//        state[i] = 1000;//初始化
//        if(v[i] == prim_root){
//            state[i] = 0;
//        }
//    }

}
void min_tree::kruskal(){

    kruskal_tree = new line_message[t_v-1];

    line_message *test = new line_message[t_message];
    for(int i = 0 ; i < t_message ; i++ ){
        test[i].va = l[i].va;
        test[i].vb = l[i].vb;
        test[i].weight = l[i].weight;
    }

    int *tree_v = new int [t_v-1];
    for(int i = 0 ; i < t_v ; i++ ){
        tree_v[i] = i;
    }

    for(int k = 0,i = 0 ; k < t_v-1 ; ){
//        int min =999,i_min = 1000;

            if(tree_v[test[i].va]!=tree_v[test[i].vb]){

                kruskal_tree[k].va = test[i].va;
                kruskal_tree[k].vb = test[i].vb;
                kruskal_tree[k].weight = test[i].weight;
                for(int j = 0 ; j < t_v ; j++ ){
                    if(j!=test[i].va&&tree_v[j]==tree_v[test[i].va])
                        tree_v[j]=tree_v[test[i].vb];
                }
                tree_v[test[i].va]=tree_v[test[i].vb];
                k++;
            }
        i++;
    }

    cout<<"kruskal:"<<endl;

    for(int i = 0 ; i < t_v-1 ; i++ ){
        cout<<v[kruskal_tree[i].va]<<" "<<v[kruskal_tree[i].vb]<<" "<<kruskal_tree[i].weight<<endl;
    }

}

bool cmp(line_message l1,line_message l2){

    return l1.weight < l2.weight;

}

int main(){

    int t;
    cin>>t;
    string *v = new string [t];
    for(int i = 0 ; i < t ; i++ ){
        cin>>v[i];
    }
    int t_message;
    cin>>t_message;
    line_message *l1 = new line_message [t_message];
    string sa,sb;
    for(int i = 0 ; i < t_message ; i++ ){
        cin>>sa>>sb>>l1[i].weight;
        for(int j = 0 ; j < t ; j++ ){
            if(sa == v[j])
                l1[i].va = j;
            else if(sb == v[j])
                l1[i].vb = j;
        }
        if(l1[i].va>l1[i].vb)
            swap(l1[i].va,l1[i].vb);
    }
    sort(l1,l1+t_message,cmp);
    string prim_root;
    cin>>prim_root;
    int i_root;
    for(int  i = 0 ; i < t ; i++ ){
        if(prim_root==v[i])
            i_root = i;
    }
    min_tree t1(t,t_message,v,l1,i_root);
    t1.prim();
    t1.kruskal();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值