描述
南阳理工学院要进行用电线路改造,现在校长要求设计师设计出一种布线方式,该布线方式需要满足以下条件:
1、把所有的楼都供上电。
2、所用电线花费最少
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开始),由于安全问题,只能选择一个楼连接到外界供电设备。
数据保证至少存在一种方案满足要求。
输出
- 每组测试数据输出一个正整数,表示铺设满足校长要求的线路的最小花费。 样例输入
-
1 4 6 1 2 10 2 3 10 3 1 10 1 4 1 2 4 1 3 4 1 1 3 5 6
样例输出
-
4
-
思路:用最小生成树prim算法,需要注意的是,因为要有一个接外电源,花费最小的话,要找一个接外电源花费最小的点开始prim
-
#include<iostream> #include<functional> #include<cstdio> #include<queue> #include<cstring> using namespace std; #define INF 999999999 int n,m; int Map[505][505],book[505]; int v[505],cas; struct node{ int place; int value; friend bool operator < (node n1,node n2){ if(n1.value!=n2.value) return n1.value>n2.value;//优先队列,按照花费从小到大排 else return n1.place>n2.place; } }u,e; int init(){ int i,j; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ Map[i][j]=INF; } } } void Prim(int st){ memset(book,0,sizeof(book)); priority_queue<node>q; while(!q.empty()) q.pop(); int i,j,sum; i=st; //printf("i=%d\n",i); for(j=1;j<=n;j++){ if(Map[i][j]!=INF){ u.place=j; u.value=Map[i][j]; q.push(u); // printf("R u.p=%d u.v=%d\n",u.place,u.value); } } book[i]=1; cas=1; sum=v[i]; while(!q.empty()){ u=q.top(); q.pop(); if(book[u.place]==1)//已经走过的点不算 continue; cas++;//记录走过点的个数 sum+=u.value;//走过点的花费 if(cas==n){ printf("%d\n",sum); break; } book[u.place]=1; // printf("C u.p=%d u.v=%d\n",u.place,u.value); i=u.place; for(j=1;j<=n;j++){ if(Map[i][j]!=INF &&book[j]==0){ e.place=j; e.value=Map[i][j]; q.push(e); // printf("R e.p=%d e.v=%d\n",e.place,e.value); } } } } int main(){ int t,a,b,c; int i,j,mm; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); init();//先把地图初始化 while(m--){ scanf("%d%d%d",&a,&b,&c); if(Map[a][b]>c){ Map[a][b]=c; Map[b][a]=c; } } mm=INF; for(i=1;i<=n;i++){ scanf("%d",&v[i]); if(v[i]<mm){ mm=v[i]; j=i; } } Prim(j);//从接外电源花费最小的点 } return 0; }