Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 4985 | Accepted: 2503 |
Description
Input
Output
Sample Input
3 10.000 10.000 50.000 10.000 40.000 10.000 50.000 10.000 40.000 40.000 50.000 10.000 2 30.000 30.000 30.000 20.000 40.000 40.000 40.000 20.000 5 5.729 15.143 3.996 25.837 6.013 14.372 4.818 10.671 80.115 63.292 84.477 15.120 64.095 80.924 70.029 14.881 39.472 85.116 71.369 5.553 0
Sample Output
20.000 0.000 73.834
题意:用最少的路将每个细胞连成MST,对于相互接触的细胞默认为已连接
思路:很明显的MST,两个槽点:1,题目最后一行扯了相交,最后又来一句不用考虑相交的情况。。。2,将已接触的细胞加入并查集居然WA,直接建边权为0的边才AC。。。
#include<iostream> #include<stdio.h> #include<cstring> #include<stdlib.h> #include<algorithm> #include<math.h> using namespace std; const int maxn=1200; const int INF=(1<<28); const double eps=0.0000001; int n; struct Cell { double x,y,z; double r; }; Cell cell[maxn]; struct Edge { int u,v; double len; friend bool operator<(Edge a,Edge b) { return a.len<b.len; } }; Edge edge[maxn*maxn];int e; int fa[maxn]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void add_edge(int i,int j) { double dist=sqrt(pow(cell[i].x-cell[j].x,2)+pow(cell[i].y-cell[j].y,2)+pow(cell[i].z-cell[j].z,2))-cell[i].r-cell[j].r; if(dist<=0) dist=0; edge[e].u=i; edge[e].v=j; edge[e++].len=dist; } double Kruskal() { double ans=0; for(int i=0;i<n;i++) fa[i]=i; e=0; for(int i=0;i<n-1;i++){ for(int j=i+1;j<n;j++){ add_edge(i,j); } } sort(edge,edge+e); for(int i=0;i<e;i++){ int x=find(edge[i].u); int y=find(edge[i].v); if(x!=y){ fa[x]=y; ans+=edge[i].len; } } return ans; } int main() { while(cin>>n,n){ for(int i=0;i<n;i++) cin>>cell[i].x>>cell[i].y>>cell[i].z>>cell[i].r; printf("%.3f\n",Kruskal()); } return 0; }
poj——2031 最小生成树(MST) Kruskal算法
原文:http://www.cnblogs.com/--560/p/4382003.html