poj2031

来源:互联网 发布:零售软件排名 编辑:程序博客网 时间:2024/05/16 14:30

题目:http://poj.org/problem?id=2031

题目大意:给定一些个球的圆心与半径,如果两个球之间相交,则他们之间连通,否则不连通,问还需要连多长的边使所有球都连通

 

解题思路:一个已存在边的最小生成树,只不过题目太难读了,任意两个球,如果连通则边权为0,否则边权为d-r1-r2,d是两球圆心坐标之间的距离,r1与r2分别为两个球的半径,这样求一个最小生成树,将所有球连接起来

kruskal:

#include <iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<string.h>using namespace std;#define maxn 1000000int n,m,t;int u[maxn],v[maxn];double  w[maxn];int r[maxn],pre[maxn];struct node{double x,y,z,d;}s[1000];int find(int x){int r=x;while(r!=pre[r])r=pre[r];int i=x,j;while(i!=r){j=pre[i];pre[i]=r;i=j;}return r;}void join (int x,int y){int fx=find(x),fy=find(y);if(fx!=fy)pre[fx]=fy;}bool cmp(int i,int j){return w[i]<w[j];}double getdis(int i,int j){double sum=(double)((s[i].x-s[j].x)*(s[i].x-s[j].x)+(s[i].y-s[j].y)*(s[i].y-s[j].y)+(s[i].z-s[j].z)*(s[i].z-s[j].z));if(sum>(s[i].d+s[j].d)*(s[i].d+s[j].d))return (double)(sqrt(sum)-s[i].d-s[j].d);else return 0;}int tot;bool check(){int ans=find(1);for(int i=2;i<=n;i++)if(find(i)!=ans)return false;return true;}void kruskal(){int t=0;for(int i=1;i<=n;i++)pre[i]=i;for(int i=0;i<tot;i++)r[i]=i;sort(r,r+tot,cmp);double sum=0;for(int i=0;i<tot;i++){int e=r[i],x=find(u[e]),y=find(v[e]);if(x!=y){sum+=w[e];pre[x]=y;}if(check())break;}printf("%.3lf\n",sum);}int main(){while(~scanf("%d",&n),n!=0){for(int i=1;i<=n;i++){scanf("%lf%lf%lf%lf",&s[i].x,&s[i].y,&s[i].z,&s[i].d);}tot=0;for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){u[tot]=i,v[tot]=j,w[tot]=getdis(i,j);tot++;}//for(int i=0;i<tot;i++)printf("%lf\n",w[i]);kruskal();}return 0;}

prim:

#include <iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#include<string.h>using namespace std;#define maxn 105int n;double maps[maxn][maxn];struct node{double x,y,z,d;}q[maxn];double getdis(int i,int j){    double x=q[i].x-q[j].x;    double y=q[i].y-q[j].y;    double z=q[i].z-q[j].z;    double sum= sqrt(x*x+y*y+z*z);    if(sum>q[i].d+q[j].d)return sum-(q[i].d+q[j].d);    else return 0;}bool vis[maxn];double dis[maxn];void prim(){memset(vis,false,sizeof vis);vis[1]=1;for(int i=2;i<=n;i++)dis[i]=maps[1][i];dis[1]=0;double sum=0;for(int i=1;i<=n;i++){int pos=-1;for(int j=1;j<=n;j++){if(!vis[j]&&(pos==-1||dis[j]<dis[pos]))pos=j;}vis[pos]=true;sum+=dis[pos];for(int j=1;j<=n;j++){if(!vis[j]&&dis[j]>maps[pos][j])dis[j]=maps[pos][j];}}printf("%.3lf\n",sum);}int main(){while(~scanf("%d",&n),n!=0){for(int i=1;i<=n;i++){scanf("%lf%lf%lf%lf",&q[i].x,&q[i].y,&q[i].z,&q[i].d);}memset(maps,0,sizeof maps);for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){maps[i][j]=maps[j][i]=getdis(i,j);}prim();}return 0;}


原创粉丝点击