首页 > 代码库 > 课程设计 问题 R: 自来水管道

课程设计 问题 R: 自来水管道

题目描述

  

你领到了一个铺设校园内自来水管道的任务。校园内有若干需要供水的点,每两个供水点可能存在多种铺设路径。对于每一种铺设路径,其成本是预知的。

 

    任务要求最终铺设的管道保证任意两点可以直接或间接的联通,同时总成本最低。

输入

每个测试用例由多行组成,第一行是两个整数P和R,P代表供水点数(1<=P<=50),每个点都对应1到P中的一个唯一编号。R代表可能的铺设路径数,路径数可能有非常多。接下有R行,每行格式如下:

节点A编号 节点B编号 路径成本

路径成本不超过100。

测试用例之间有一空行分开。输入结束用P=0表示,注意没有R值。

输出

    每个测试用例占用一行输出最低总成本。

样例输入

1 0

2 3
1 2 37
2 1 17
1 2 68

3 7
1 2 19
2 3 11
3 1 7
1 3 5
2 3 89
3 1 91
1 2 32

5 7
1 2 5
2 3 7
2 4 8
4 5 11
3 5 10
1 5 6
4 2 12

0

样例输出

0
17
16
26


题意:P个点,给出两个点间的间的距离,求最小生成树所需的成本。
思路:克鲁斯卡尔算法。将给出的边按权值进行排序,遍历所有的边,如果该边的两个顶点不连通,则加入到生成树中。
用sort函数排序权值。关键在于判断该两点是否连通。我用了并查集的思想。若两点联通则将一点的终节点指向另一点的终节点(用了数组b来存,b[i]就表示节点i指向的下一个节点)。
先初始化,让b[i]=i。用自定义函数f(i)求i节点的终节点。如果两节点a,b的f(a)和f(b)不想等。说明a,b,两节点不连通。


#include<cstdio>
#include<algorithm>
using namespace std;
typedef struct
{
    int v[3];
} p;                   //用来存两个供水点和之间的距离
bool comp(p a, p b)    //按v[2]中的元素进行比较
{
    return a.v[2] < b.v[2];
}
p a[10000005];
int b[105];
int f(int i)          //寻找终节点
{
    if(b[i]==i) return i;
else return f(b[i]); //应该可以优化成 return b[i]=f(b[i]); } int main() { int i,t,n,s,j; while(scanf("%d",&n)==1&&n) { s=0; scanf("%d",&t); for(i=1; i<=t; i++) scanf("%d%d%d",&a[i].v[0],&a[i].v[1],&a[i].v[2]); sort(a,a+t,comp); for(i=1; i<=n; i++) b[i]=i; for(i=1; i<=t; i++) { if(f(a[i].v[0])!=f(a[i].v[1])) //如果不连通就加入生成树中并累加路径 { s+=a[i].v[2]; b[f(a[i].v[0])]=f(a[i].v[1]); //将一点的终节点指向另一点的终节点 } } printf("%d\n",s); } return 0; }

 

课程设计 问题 R: 自来水管道