最小生成树--Agri-Net(poj 1258);

时间:2021-02-28 11:40:04
农业网
时限:1000MS 内存限制:10000K
提交材料共计: 62643 接受: 25922
描述


农夫约翰被选为他的镇长!他的竞选承诺之一是将互联网连接到该地区的所有农场。他当然需要你的帮助。
农场主约翰为他的农场订购了一条高速连接,并将与其他农民分享他的连接。为了降低成本,他想要铺设最少的光纤来连接他的农场和所有其他农场。
给出连接每一对农场需要多少纤维的清单,你必须找到将它们连接在一起所需的最小纤维数量。每个农场必须连接到其他农场,以便一个包可以从任何一个农场流到任何其他农场。

两个农场之间的距离不超过100000。


输入
输入包括几个案例。对于每一种情况,第一行包含农场的数量,n(3<=n<=100)。下面的行包含在矩阵,其中每个元素显示从农场到另一个农场的距离。从逻辑上讲,它们是n个空间分离整数的n行.。在物理上,它们的长度限制为80个字符,因此有些行继续在其他行上。当然,对角线是0,因为从农场i到它本身的距离对于这个问题并不有趣。
输出
对于每个情况,输出一个整数长度,这是连接整个农场集所需的最小纤维长度之和。
样本输入


4
0  4  9 21
4  0  8 17
9  8  0 16
21 17 16 0
样本输出

28


方法一、克鲁斯卡尔算法实现:


#include <iostream>
#include <cstdio>
#define NUM 105
using namespace std;
int N;//农场的数量
int Graph[NUM][NUM];


int K_r_Agri()
{
    int totle_value = 0;
    int set[NUM];
    for(int i = 1;i<=N;i++)
        set[i] = i;//初始化set数组
    int k = 1;
    int a = 1;
    int b = 1;
    int min_ = 1<<30;//找到最小的权值;(也就是最小的距离)
    while(k<=N-1){
        for(int i = 1;i<=N;i++)
            for(int j = i+1;j<=N;j++)
                if(Graph[i][j]<min_){
                    min_ = Graph[i][j];
                    a = i;
                    b = j;
                }
        int temp = min_;
        min_ = Graph[a][b] = 1<<30;
        if(set[a]!=set[b]){
            totle_value+=temp;
            k++;
            int t = set[b];
            for(int i = 1;i<=N;i++)
                if(set[i]==t)
                    set[i] = set[a];
        }

    }
    return totle_value;
}





int main()
{
    while(~scanf("%d",&N)){
    for(int i = 1;i<=N;i++)
        for(int j = 1;j<=N;j++)
            cin>>Graph[i][j];

    cout <<K_r_Agri()<<endl;
    }


    return 0;
}


方法二:克鲁斯算法二:


#include <iostream>
#include <cstdio>
#define NUM 105
using namespace std;
int N,m;//农场的数量和边数

struct dot_line
{
    int W;
    int V;
    int U;

}DL[NUM*NUM/2];//是一个结构体内东西:其中有 顶点坐标,两个定点之间的权值;

int xu_hao[NUM*NUM/2];//边的序号
int set[NUM];//表示nUM个顶点的是否都在哎统一集合中;(也就是入树)

int find(int x){
    return set[x] == x? x: set[x] = find(set[x]);
}
int com(const int a,const int b){
    return DL[a].W<DL[b].W;
}


int K_r_Agri()
{
    int totle_value = 0;
    for(int i=0;i<N;i++)
        set[i] = i;
    for(int i = 0;i<m;i++)
        xu_hao[i] = i;
    sort(xu_hao, xu_hao+m, com);//对边进行排序;
    for(int i = 0;i<m;i++){
        int e = xu_hao[i];
        int a = find(DL[e].U);
        int b = find(DL[e].V);
        if(a!=b){
            totle_value+=DL[e].W;
            set[a] = b;
        }
    }


    return totle_value;
}






int main()
{
    while(~scanf("%d",&N)){
        m = 0;
        for(int i = 0;i<N;i++)
            for(int j = 0;j<N;j++)
                if(i<j){
                    DL[m].U = i;
                    DL[m].V = j;
                    cin>>DL[m].W;
                    m++;
                }
                else{
                    int k ;
                    cin>>k;
                }
//
//        for(int i = 0;i<m;i++)
//            cout <<W[i]<<" ";
//        cout <<endl;

    cout <<K_r_Agri()<<endl;
    }


    return 0;
}


3、普利姆算法:

#include <iostream>
#include <cstdio>

#define NUM 105
using namespace std;
int N,m;//农场的数量和边数
int Graph[NUM][NUM];

struct set
{
    int adj;//顶点号
    int value;
}SET[NUM];

int min_xu()
{
    int i = 1;
    while(!SET[i].value&&i<=N)
        i++;
    int k = i;
    int min = 1<<30;
    for(int i = 1;i<=N;i++)
        if(SET[i].value>0&&SET[i].value<min)
            {min = SET[i].value;k = i;}
    return k;
}



int Prim()
{
    int ans  = 0;
    for(int i = 1;i<=N;i++){
        SET[i].adj = 1;
        SET[i].value = Graph[1][i];
    }
    SET[1].value = 0;//入集合;
    for(int i = 1;i<N;i++){
        int k = min_xu();
        ans+=SET[k].value;
        SET[k].value = 0;
        for(int i = 1;i<=N;i++)
            if(SET[i].value>Graph[k][i]){
                SET[i].adj = k;
                SET[i].value = Graph[k][i];
            }
    }
    return ans;

}




int main()
{
    while(~scanf("%d",&N)){
        for(int i = 1;i<=N;i++)
            for(int j = 1;j<=N;j++){
                scanf("%d",&Graph[i][j]);
                if(Graph[i][j] == 0)
                    Graph[i][j] = 1<<30;
            }


        printf("%d\n",Prim());
    }

    return 0;
}