1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define MAX 0xffffffff //定义一个最小生成树中不可能达到的值 7 const int qq=100+10; // 点的上限 8 using namespace std; 9 struct point{ 10 int x,y; 11 }node[qq]; 12 double lowcost[qq][qq]; // 邻接矩阵 13 int vis[qq]; // 最小生成树的点集合vis数组 14 int n; 15 double f(point a,point b) 16 { 17 return sqrt(pow(a.x-b.x,2.0)+pow(a.y-b.y,2.0)); 18 } 19 void build() 20 { 21 double len; 22 for(int j,i=0;i<n;++i) 23 for(j=i;j<n;++j){ 24 len=f(node[i],node[j]); // 计算两点之间的距离也就是点与点的权值、 25 if(len>=10&&len<=1000) 26 lowcost[i][j]=lowcost[j][i]=(i==j)?0:len; 27 else 28 lowcost[i][j]=lowcost[j][i]=MAX; // 值为MAX 意味着这两点不连通、 29 } 30 } 31 void prim() 32 { 33 int k,t=n; 34 double min,tot=0; 35 vis[0]=0; //初始点0进入最小生成树数组中、 36 while(--t){ 37 min=MAX; 38 for(int i=1;i<n;++i){ 39 if(vis[i]!=0&&lowcost[0][i]<min){ //lowcost[0]代表当前的最小生成树的最小权值数组、 40 min=lowcost[0][i]; //找到当前最小的权值并记录是哪一个点、 41 k=i; 42 } 43 } 44 if(min==MAX) break; //如果最小权值都为MAX 也就是不连通也可以跳出循环了、 45 vis[k]=0; // 点k进入最小生成树数组、 46 tot+=min; //统计权值、 47 for(int i=1;i<n;++i) //因为加入了一个点到最小生成树中,所以要更新当前的最小权值数组、 48 if(vis[i]!=0&&lowcost[k][i]<lowcost[0][i]) 49 lowcost[0][i]=lowcost[k][i]; 50 } 51 if(t==0) printf("%.1f ",tot*100); 52 else printf("oh! "); 53 } 54 int main() 55 { 56 int t;cin >> t; 57 while(t--){ 58 memset(vis,1,sizeof(vis)); //清空标记数组、 59 scanf("%d",&n); 60 for(int i=0;i<n;++i) 61 scanf("%d%d",&node[i].x,&node[i].y); 62 build(); 63 prim(); 64 } 65 }
刚做这题我模型没转换过来,以为只要把横坐标按从小到大排序,横坐标相同就按纵坐标从小到大排序然后然后从左到右从下道上连接各点就是最小生成树、
- - 、 错的太离谱了,代码就不拿出来丢脸了
题目设置的限制条件实际上就是不连通,这点想通了就好做了