布线问题
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件:
1、把所有的楼都供上电。
2、所用电线花费最少
-
输入
-
第一行是一个整数n表示有n组测试数据。(n<5)
每组测试数据的第一行是两个整数v,e.
v表示学校里楼的总个数(v<=500)
随后的e行里,每行有三个整数a,b,c表示a与b之间如果建铺设线路花费为c(c<=100)。(哪两栋楼间如果没有指明花费,则表示这两栋楼直接连通需要费用太大或者不可能连通)
随后的1行里,有v个整数,其中第i个数表示从第i号楼接线到外界供电设施所需要的费用。( 0<e<v*(v-1)/2 )
(楼的编号从1开始),由于安全问题,只能选择一个楼连接到外界供电设备。
数据保证至少存在一种方案满足要求。
-
第一行是一个整数n表示有n组测试数据。(n<5)
典型的最小生成树问题:
Prim算法生成最小生成树
我采用的是普里姆算法:
普里姆算法和迪杰斯特拉算法有点相似。
参考普利姆算法代码:
void MiniSpanTree_Prim(MGraph MG)
{
intmin, i, j, k;
intadjvex[MAXVEX]; 保存相关顶点下标
intlowcost[MAXVEX]; 保存相关顶点间边的权值
lowcost[0]= 0; 初始化第一个权值为0,即v0加入生成树
lowcost的值为0,在这里就是此下标的顶点已经加入生成树
adjvex[0]= 0; 初始化第一个顶点下标为0
cout<< "最小生成树的边为:" << endl;
for(i = 1; i < MG.numVertexes; i++)
{
lowcost[i]= MG.arc[0][i]; 将v0顶点与之有边的权值存入数组
adjvex[i]= 0; 初始化都为v0的下标
}
for(i = 1; i < MG.numVertexes; i++)
{
min= INFINITY; 初始化最小权值为∞,
j= 1;
k= 0;
while(j < MG.numVertexes) 循环全部顶点
{
if(lowcost[j] != 0 && lowcost[j] < min) 如果权值不为0且权值小于min
{
min= lowcost[j]; 则让当前权值成为最小值
k= j; 将当前最小值的下标存入k
}
j++;
}
cout<< "(" << adjvex[k] << ", " << k <<")" << " "; 打印当前顶点边中权值最小的边
lowcost[k]= 0; 将当前顶点的权值设置为0,表示此顶点已经完成任务
for(j = 1; j < MG.numVertexes; j++) 循环所有顶点
{
如果下标为k顶点各边权值小于此前这些顶点未被加入生成树权值*/
if(lowcost[j] != 0 && MG.arc[k][j] < lowcost[j])
{
lowcost[j]= MG.arc[k][j]; 将较小的权值存入lowcost相应位置
adjvex[j]= k; 将下标为k的顶点存入adjvex
}
}
}
cout<< endl;
}
本题代码:
#include"stdio.h"
#define Inlimit 1<<30
#define N 505
int Map[N][N];
void initi(){
for(inti=0;i
for(intj=0;j
Map[i][j]=Inlimit;
}
int Prim(int v)
{
intdmin, i, j, k;
intadjvex[N];
intlowcost[N];
intans=0;
lowcost[0]= 0;
lowcost[1]=0;
adjvex[0]= 0;
adjvex[1]= 1;
for(i = 2; i < v; i++)
{
lowcost[i]= Map[1][i];
adjvex[i]= 1;
}
for(i = 2; i < v; i++)
{
dmin= Inlimit;
j= 2;
k= 1;
while(j < v)
{
if(lowcost[j] != 0 && lowcost[j] < dmin)
{
dmin= lowcost[j];
k= j;
}
j++;
}
ans+=Map[k][adjvex[k]];
lowcost[k]= 0;
for(j = 2; j < v; j++)
{
if(lowcost[j] != 0 && Map[k][j] < lowcost[j])
{
lowcost[j]= Map[k][j];
adjvex[j]= k;
}
}
}
returnans;
}
int main()
{
intt;
scanf("%d",&t);
intv,e;
inta,b,c;
while(t--&&scanf("%d%d",&v,&e)){
initi();
for(inti=0;i
scanf("%d%d%d",&a,&b,&c);
if(Map[a][b]>c)
Map[a][b]=Map[b][a]=c;
}
intvmin=Inlimit;
for(inti=1;i<=v;i++){
scanf("%d",&a);
if(vmin>a)
vmin=a;
}
intans=Prim(v+1)+vmin;
printf("%d\n",ans);
}
}