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 算法。
#include<stdio.h> #include<string.h> #define MAX_N 505 #define INF 0x3f3f3f3f #include<algorithm> using namespace std; int cost[MAX_N][MAX_N]; //表示边的权值(不存在的情况设为INF) int mincost[MAX_N]; //从集合X出发得边到每个顶点的最小权值 bool used[MAX_N]; //顶点i是否包含在集合X(最小生成树)中 int v; //顶点数目 int prim() //prim算法模板 { for(int i = 1;i <= v;i++) //初始化 { mincost[i] = INF; used[i] = false; } mincost[1] = 0; int res = 0; while(true) { int e = -1; // 从不属于X的顶点中选取从X到其权值最小的顶点 for(int i = 1;i <= v;i++) { if(used[i] == false && (e == -1 || mincost[i] < mincost[e])) e = i; } if(e == -1) break; used[e] = true; res += mincost[e]; for(int i = 1;i <= v;i++) { mincost[i] = min(mincost[i],cost[e][i]); } } return res; } int main() { int n; scanf("%d",&n); while(n--) { memset(cost,INF,sizeof(cost)); int e; scanf("%d%d",&v,&e); int a,b,c; for(int i = 1;i <= e;i++) { scanf("%d%d%d",&a,&b,&c); cost[a][b] = cost[b][a] = min(cost[a][b],c);//只记录连接两个楼的最小花费 } int minn = INF,x; //找到连接外界供电设备最小的花费 for(int i = 1;i <= v;i++) { scanf("%d",&x); minn = min(minn,x); } printf("%d\n",minn + prim());//最终答案即连接v个楼的最小花费与minn之和 } return 0; }