zoj 1203求最小生成树的权值之和(kruskal算法实现)

来源:互联网 发布:python print 编辑:程序博客网 时间:2024/05/22 01:33

这道zoj的题目,主要运用的是求最小生成树的知识,我用的是kruskal算法,当然,用取权值最小边的最小堆和查看是否有回路的并查集是自己实现的。但提交了几次都没成功,查了下,原来是自己的输出格式没有正确。看来以后要特别注意这方面的问题。


#include <iostream>#include <queue>#include <cstdio>#include <cmath>#include <memory.h>using namespace std;/**********************堆***************************/int heapNum=0; //记录堆的结点个数//堆的结点结构struct Heap{int sta,en;double weight;} heap[5000];//下滑操作void siftDown(int start,int end){//将start号结点向下调整直到endint i=start,j=2*i;heap[0]=heap[i]; //用heap[0]来临时保存i结点的值while(j<=end){//有右孩子并且右孩子比左孩子小时,将j保存右孩子if(j<end&&heap[j].weight>heap[j+1].weight) ++j;//比j号结点小时,不需调整if(heap[0].weight<=heap[j].weight) break;else{//向下调整heap[i]=heap[j];i=j;j=2*j;}}heap[i]=heap[0];}void siftUp(int start){int j=start,i=j/2;heap[0]=heap[j];while(j>0){if(heap[i].weight<=heap[0].weight)break;else{//向上调整工作heap[j]=heap[i];j=i;i=i/2;}}heap[j]=heap[0];}//插入操作的实现bool insert(Heap temp){++heapNum;heap[heapNum]=temp;siftUp(heapNum);return true;}//删除操作bool removeMin(Heap& temp){//保留下根结点temp=heap[1];heap[1]=heap[heapNum]; //填补树根--heapNum;siftDown(1,heapNum); //将根结点下滑到尾部return true;}/***************************并查集********************/int parent[101];//查找i所在的集合的元首,并对该树形结构进行优化int collaspingFind(int i){int r=i;for(;parent[r]>=0;r=parent[r]);while(i!=r){int s=parent[i];parent[i]=r;i=s;}return r;}void weightedUnion(int i,int j){int temp=parent[i]+parent[j];//负数值大的反而小,树i的结点较小时if(parent[j]<parent[i]){parent[i]=j;  //将i的父亲设为jparent[j]=temp;}else{parent[j]=i;parent[i]=temp;}}/******************************图模块*********************************/struct LinkNode{int vex; //邻接的结点在数组中的编号LinkNode* next;double weig; //结点的权值};//定义图结点的最大个数const int MaxSize=101;struct Node{//int data;LinkNode* head;//将结点邻接的链表头置为空Node(){ head=0;}} Adj[MaxSize]; //Adj数组表示原来的图//坐标结构体struct Coord{double x;double y;} coord[101];//求坐标中两点距离的函数double sqrtCoord(const Coord& c1,const Coord& c2){return sqrt((c1.x-c2.x)*(c1.x-c2.x)+(c1.y-c2.y)*(c1.y-c2.y));}//建立图的算法void createLink(int& numNode){int numLink=0;LinkNode* ptr=0;//赋初值memset(Adj,0,sizeof(Adj));for(int i=1;i<=numNode;++i)scanf("%lf%lf",&coord[i].x,&coord[i].y);for(int i=1;i<=numNode;++i){//头插入建表for(int j=i+1;j<=numNode;++j){ptr=new LinkNode;ptr->vex=j;ptr->weig=sqrtCoord(coord[i],coord[j]);ptr->next=Adj[i].head;Adj[i].head=ptr;}}}/**************************最小生成树的模块*****************///将图中的所有边存入堆中void inHeap(int& numNode){//将堆的结点个数重置为0heapNum=0;memset(heap,0,sizeof(heap));LinkNode* ptr=0;for(int v=1;v<=numNode;++v){ptr=Adj[v].head;//每个邻接点都有机会访问while(ptr!=0){//将图中的边和所关联的两个结点压入堆中Heap temp;temp.sta=v;temp.en=ptr->vex;temp.weight=ptr->weig;insert(temp);ptr=ptr->next; //到下个邻接点}}}//求出最小生成树的权值之和void kruskal(){int nodeNum=0;int testNum=1; //程序执行的次数while(scanf("%d",&nodeNum)!=EOF&&nodeNum!=0){createLink(nodeNum);//初始化并查集for(int i=1;i<=nodeNum;++i)parent[i]=-1;//将所有边存入堆中inHeap(nodeNum);int cntNum=1;double miniLen=0.0;while(cntNum<nodeNum){Heap temp;//取堆中权值最小的结点removeMin(temp);int stRoot=collaspingFind(temp.sta);int enRoot=collaspingFind(temp.en);if(stRoot!=enRoot){weightedUnion(stRoot,enRoot);miniLen+=temp.weight;++cntNum;}}//要特别注意输出格式!!前几次提交应格式错误告终。。if(testNum!=1 )  printf( "\n" );        printf( "Case #%d:\n",testNum);        printf( "The minimal distance is: %.2lf\n",miniLen);        ++testNum;}}int main(){ kruskal();}