网络楼楼通

  现有学校宿舍区之间要铺设光纤建设网络,在施工预算的统计数据表中,列出了有可能建设光缆的若干条管线的成本,求使每栋楼都能够接入校园网且使管网建设费用成本最低。

输入:
    第一行数据包括楼宇的数目正整数N(≤1000)和候选管网数目M(≤3N);
    随后的M行对应M条线路,每行给出3个正整数,分别是该条线路直接连通的两个楼宇的编号以及预算成本(为简单起见,城镇从1到N编号)。

输出:
    输出建设楼楼通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多的通路。

思路:

 1)首先要建立网络楼连通之间的图

 2)对节点之间路径的加权赋值

 3)每次都选择路径最短的一个环,同时要判断是否成环,这就是kruskal克鲁斯卡尔算法,

我们借助并查集(并查集)来判断是否成环:即对于某个新选择的环,我们需要判断的就是新选择的这个节点是否与已选择的节点成环,成环的判断就是这两个节点的头(即通过并查集找到头)是否相同,不相同才可以选择。

        这是对并查集的代码:

void init()  
{  
    for (int i = 0; i <= n; i++)  
    {  
        tree[i] = i;  
    }  
}  
  
int find(int t)  
{  
    if (tree[t] == t)  
    {  
        return t;  
    }  
    else  
    {  
        return tree[t] = find(tree[t]);  
    }  
}  

完整代码:

#include<iostream>  
#include<algorithm>  
  
using namespace std;  
  
struct node {  
    int x;  
    int y;  
    int cost;  
};  
  
node road[5000];  
  
struct cmp  
{  
    bool operator()(const node& A, const node& B) const  
    {  
        return A.cost < B.cost;  
    }  
};  
  
int tree[1000];  
int n, m;  
  
void init()  
{  
    for (int i = 0; i <= n; i++)  
    {  
        tree[i] = i;  
    }  
}  
  
int find(int t)  
{  
    if (tree[t] == t)  
    {  
        return t;  
    }  
    else  
    {  
        return tree[t] = find(tree[t]);  
    }  
}  
int judge(int x, int y)  
{  
    int a = find(x);  
    int b = find(y);  
    if(a != b)  
    {  
        tree[a] = b;  
        return 1;  
    }  
    else  
    {  
        return 0;  
    }  
}  
void kruskal()  
{  
    int side = 0;  
    int sum = 0;  
    init();  
    sort(road, road + m, cmp());  
    for (int i = 0; i < m; i++)  
    {  
        if (judge(road[i].x, road[i].y))  
        {  
            side++;  
            sum += road[i].cost;  
        }  
        if (side == n - 1)  
        {  
            break;  
        }  
    }  
        if (side != n - 1)  
        {  
            cout << "-1" << endl;  
        }  
        else  
        {  
            cout << sum << endl;  
        }  
      
}  
int main()  
{  
    cin >> n >> m;  
    for (int i = 0; i < m; i++)  
    {  
        cin >> road[i].x >> road[i].y >> road[i].cost;  
    }  
    kruskal();  
    return 0;  
  
} 
思考:

        并不是所有图的问题都是一样的解决办法,根据题目所需要求的东西进行设计数据结构。

如要建立无向图以及遍历等,就需要邻接表、邻接矩阵、十字链表(有向图)等方式进行完整的建立结构,邻接表结构就需要信息:c(端点信息)、visit(遍历)、chain(邻接表水平)、cnum(邻接表下标)

但如本题重点关注的是环,以及环的两端对应的节点,因此本题对环结构化,除cost信息外,取x,y为两个端点即可。重点为kruskal克鲁斯卡尔算法&&并查集对是否成环的初始化和检查这个结构。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值