题意为恐怖分子要炸理工,但是要把炸弹连接起来,那样才放便作案。问怎么样才能用最短的线把炸弹都连接起来。
用到最小生成树的算法。
prim 算法:任意找一点A为树,以这个点为起点找离它最近的点的距离设为点B,再把B加入树,以(A,B)为整体,找离她们两个最近的距离设为点C ,把C也加入到树中。依次类推。
Kruskal 算法:先对所有距离从小到大排列,由小到大依次找,如果前面的距离是当前距离的一个集合(也就是当前的距离是否包括前面多了距离),不包括了加入到距离中,否则不加;
1 /*#include<stdio.h>//kruskal算法实现 2 #include<stdlib.h> 3 int r[5000],u[5000],v[5000],w[5000],p[102]; 4 int n,b; 5 int cmp(const void*p1,const void*p2) 6 { 7 return w[*(int*)p1]>w[*(int*)p2]; 8 } 9 int find(int x) 10 { 11 int r=x,i,j; 12 while(p[r]!=r) 13 r=p[r]; 14 i=x; 15 while(i!=r) 16 { 17 j=p[i]; 18 p[i]=r; 19 i=j; 20 } 21 return r; 22 } 23 void join(int x,int y) 24 { 25 int fx=find(x),fy=find(y); 26 if(fx!=fy) 27 { 28 if(fx<fy) 29 p[fy]=fx; 30 else 31 p[fx]=fy; 32 } 33 } 34 int kruskal() 35 { 36 int ans=0; 37 int x,y,i,e; 38 for(i=0;i<n;i++) 39 p[i]=i; 40 for(i=0;i<b;i++) 41 r[i]=i; 42 qsort(r,b,sizeof(r[0]),cmp); 43 for(i=0;i<b;i++) 44 { 45 e=r[i]; 46 x=find(u[e]); 47 y=find(v[e]); 48 if(x!=y) 49 { 50 ans+=w[e]; 51 join(x,y); 52 } 53 } 54 return ans; 55 } 56 int main() 57 { 58 int i,j,t,p; 59 while(scanf("%d",&t)!=EOF) 60 while(t--) 61 { 62 b=0; 63 scanf("%d",&n); 64 for(i=0;i<n;i++) 65 for(j=0;j<n;j++) 66 { 67 scanf("%d",&p); 68 if(i<j) 69 { 70 u[b]=i;v[b]=j;w[b]=p;b++; 71 } 72 } 73 printf("%d\n",kruskal()); 74 } 75 return 0; 76 }*/ 77 #include<stdio.h>//prim 算法实现 78 #include<string.h> 79 int map[101][101],visit[101],min[101]; 80 int main() 81 { 82 int t,n,sum,k,i,minnum,j; 83 while(scanf("%d",&t)!=EOF) 84 { 85 while(t--) 86 { 87 sum=0; 88 scanf("%d",&n); 89 memset(visit,0,sizeof(visit)); 90 for(i=1;i<=n;i++) 91 for(j=1;j<=n;j++) 92 scanf("%d",&map[i][j]); 93 for(j=1;j<=n;j++) 94 min[j]=map[1][j]; 95 visit[1]=1; 96 for(i=2;i<=n;i++) 97 { 98 minnum=10000; 99 for(j=1;j<=n;j++) 100 { 101 if(!visit[j]&&min[j]<minnum) 102 { 103 minnum=min[j]; 104 k=j; 105 } 106 } 107 sum+=minnum; 108 visit[k]=1; 109 for(j=1;j<=n;j++) 110 { 111 if(!visit[j]&&map[k][j]<min[j]) 112 min[j]=map[k][j]; 113 } 114 } 115 printf("%d\n",sum); 116 } 117 } 118 return 0; 119 }