标签:c++
题目链接:
题意:
一个平面图中有N个城镇,标号1~N,给出这N个城镇的坐标,并给出一些已经建设好的公路,问要完成最小生成树还需要建设哪些公路。
题解 :
prim:用邻接矩阵保存所有城镇之间的距离,已建好的距离则为0;建立一个pre数组
表示当前城镇的(在最小生成树中的)前一个城镇,开始初始化为1,在更新low_distance数组时一起更新,最后pre数组保存的都是最近的城镇。最后遍历
edge[pre[i]][i],输出时去掉距离为0的即可。
kruskal:并查集时间消耗的比较大,但思路更加简洁:建边,排序,遍历所有边
如果边的两端不在一个集合且权值不为0则输出两端。
后来用到了几个优化:
1.不用计算距离 , 即 不用sqrt() 因为这道题没有要求算距离 2.已有的边直接把它们用并查集并到一块 不用什么把它们距离设为0在加进去 prim代码:#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; #define maxx 9999999 double lowdis[777]; double map[777][777]; double loc[777][2]; int pre[777]; int m,n; void prim() { int i,j,pos; double minn; for(i=1; i<=m; i++) lowdis[i]=map[1][i],pre[i]=1; lowdis[1]=-1; for(i=1; i<m; i++) { minn=maxx; for(j=1; j<=m; j++) if(lowdis[j]!=-1&&lowdis[j]<minn) minn=lowdis[j],pos=j; lowdis[pos]=-1; for(j=1; j<=m; j++) if(lowdis[j]>map[pos][j]) lowdis[j]=map[pos][j],pre[j]=pos; } return; } int main() { int t,i,j,a,b; scanf("%d",&m); for(i=1; i<=m; i++) scanf("%lf%lf",&loc[i][0],&loc[i][1]); for(i=1; i<=m; i++) for(j=1; j<=m; j++) { if(i==j) map[i][j]=maxx; else map[i][j]=map[j][i]=sqrt(pow(loc[i][0]-loc[j][0],2)+pow(loc[i][1]-loc[j][1],2)); } scanf("%d",&n); while(n--) { scanf("%d%d",&a,&b); map[a][b]=map[b][a]=0; } prim(); for(i=2; i<=m; i++) if(map[pre[i]][i]!=0) cout<<pre[i]<<' '<<i<<endl; return 0; }
kruskal代码:#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; struct node { int u,v,w; } edge[777*777/2]; int fa[777]; int loc[777][2]; int m,n,s; int cmp(node a,node b) { return a.w<b.w; } int find(int x) { int t,d=x; while(fa[d]>=0) d=fa[d]; while(x!=d) { t=fa[x]; fa[x]=d; x=t; } return d; } void Kruskal() { int r1,r2,i,j,ss,nn=0; for(i=0; i<s; i++) { r1=find(edge[i].u); r2=find(edge[i].v); if(r1!=r2) { nn++; if(edge[i].w!=0) cout<<edge[i].u<<' '<<edge[i].v<<endl; ss=fa[r1]+fa[r2]; if(fa[r1]<fa[r2]) fa[r1]=ss,fa[r2]=r1; else fa[r1]=r2,fa[r2]=ss; } if(nn==m-1) break; } return; } int main() { int i,j,k,a,b; s=0; scanf("%d",&m); memset(fa,-1,sizeof(fa)); for(i=1; i<=m; i++) scanf("%d%d",&loc[i][0],&loc[i][1]); for(i=1; i<=m; i++) for(j=i+1; j<=m; j++) { edge[s].u=i,edge[s].v=j; edge[s++].w=(loc[i][0]-loc[j][0])*(loc[i][0]-loc[j][0])+(loc[i][1]-loc[j][1])*(loc[i][1]-loc[j][1]); } scanf("%d",&n); while(n--) { scanf("%d%d",&a,&b); if(find(a)!=find(b)) fa[find(a)]=find(b); } sort(edge,edge+s,cmp); Kruskal(); return 0; }
标签:c++
原文地址:http://blog.csdn.net/axuan_k/article/details/43085667