【最小生成树】畅通工程再续

畅通工程再续

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 16   Accepted Submission(s) : 12
Problem Description
相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现。现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全畅通!经过考察小组RPRush对百岛湖的情况充分了解后,决定在符合条件的小岛间建上桥,所谓符合条件,就是2个小岛之间的距离不能小于10米,也不能大于1000米。当然,为了节省资金,只要求实现任意2个小岛之间有路通即可。其中桥的价格为 100元/米。
 

 

Input
输入包括多组数据。输入首先包括一个整数T(T <= 200),代表有T组数据。 每组数据首先是一个整数C(C <= 100),代表小岛的个数,接下来是C组坐标,代表每个小岛的坐标,这些坐标都是 0 <= x, y <= 1000的整数。
 

 

Output
每组输入数据输出一行,代表建桥的最小花费,结果保留一位小数。如果无法实现工程以达到全部畅通,输出”oh!”.
 

 

Sample Input
2
2
10 10
20 20
3
1 1
2 2
1000 1000
 

 

Sample Output
1414.2
oh!
 

 

Author
8600
 

 

Source
2008浙大研究生复试热身赛(2)——全真模拟
题目大意:
  输入T,表示有T组数据,每一组数据先输入N,表示有N个点,然后下面有N行,每一行分别输入地1~N的坐标(x,y),然后要在这些点直接建桥,桥的长度不能小于10且不能够大于1000,问你连接着N个点,所需要建桥的长度总和的最小值(*100)。如果连接所有点,则输出oh!
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <math.h>
 5 #define MAXN 205
 6 #define inf 1000000000
 7 double Map[MAXN][MAXN];
 8 void Crate_MAP(int N)
 9 {
10     int i,j;
11     for(i=1;i<=N;i++)
12         for(j=1;j<=N;j++)
13         {
14             if(i==j)
15                 Map[i][j]=0;
16             else
17                 Map[i][j]=inf;
18         }
19 }
20 double Prim(int N,int* pre)
21 {
22     double min[MAXN],ret=0;
23     int v[MAXN],i,j,k;
24     for (i=1;i<=N;i++)
25         min[i]=inf,v[i]=0,pre[i]=-1;
26     for (min[j=1]=0;j<=N;j++)
27     {
28         for (k=-1,i=1;i<=N;i++)
29             if (!v[i]&&(k==-1||min[i]<min[k]))
30                 k=i;
31         for (v[k]=1,ret+=min[k],i=1;i<=N;i++)
32             if (!v[i]&&Map[k][i]<min[i])
33                 min[i]=Map[pre[i]=k][i];
34     }
35     return ret;
36 }
37  double Dic(double a,double b)
38  {
39     double sum=a*a+b*b;
40     if(sum>0)return sum;
41     else return (-sum);
42  }
43 int main()
44 {
45     double a[105],b[105],sum;
46    int T,N,i,j,c,pre[205],sign;
47    scanf("%d",&T);
48    while(T--)
49    {
50        sign=0;
51        scanf("%d",&N);
52        Crate_MAP(N);
53        memset(pre,0,sizeof(pre));
54        for(i=1;i<=N;i++)
55             scanf("%lf%lf",&a[i],&b[i]);
56          for(i=1;i<=N;i++)
57              for(j=i+1;j<=N;j++)
58              {
59                 sum=sqrt(Dic(a[i]-a[j],b[i]-b[j]));
60                 if(sum<10||sum>1000)continue;
61                 if(Map[i][j]==inf)sign++;
62                 if(Map[i][j]>sum)
63                 {
64                     Map[i][j]=sum;
65                     Map[j][i]=sum;
66                 }
67              }
68         if(sign>=N-1)
69             printf("%.1lf\n",100*Prim(N,pre));
70         else
71             printf("oh!\n");
72    }
73    return 0;
74 }
View Code

 修改:2015.6.8(Prim)

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <math.h>
 5 #define MAX 1100
 6 using namespace std;
 7 struct node
 8 {
 9     double x,y;
10 }POINT[MAX];
11 int Point[MAX];/*标记点i的状态*/
12 void Cread(int N)
13 {
14     for(int i=0;i<=N;i++)Point[i]=1;
15 }
16 
17 double DIC(double x,double y)
18 {
19     return sqrt(x*x+y*y);
20 }
21 double Prim(int N)/*如果可构成最小生成树,返回最小权值*/
22 {       /*否则返回-1,表示无法构成最小生成树,O(N^3)*/
23     int i,j,k,ii,jj;
24     double Sum_Min=0,MIN,TMD;
25     int P[MAX]={0};/*记录点集合*/
26     double PX,PY;
27     P[1]=1;Point[1]=0;
28     for(k=2;k<=N;k++)
29     {
30         for(i=1,MIN=1000010;i<k;i++)
31         {
32             for(j=1;j<=N;j++)
33             {
34                 if(Point[j])
35                 {
36                     PX=POINT[P[i]].x-POINT[j].x;
37                     PY=POINT[P[i]].y-POINT[j].y;
38                     TMD=DIC(PX,PY);
39                     if(TMD>=10&&TMD<=1000)
40                     {
41                         if(TMD<MIN)
42                         {
43                             ii=P[i];jj=j;
44                             MIN=TMD;
45                             P[k]=j;
46                         }
47                     }
48                 }
49             }
50         }
51         if(MIN==1000010)break;
52         Sum_Min+=MIN;
53         Point[P[k]]=0;
54     }
55     if(k==N+1)return Sum_Min;
56     else return -1;
57 }
58 int main()
59 {
60     int i,j,k,N,M,T;
61     scanf("%d",&T);
62     while(T--)
63     {
64         scanf("%d",&N);
65         Cread(N);
66         double a,b;
67         for(i=1;i<=N;i++)
68         {
69             scanf("%lf%lf",&a,&b);
70             POINT[i].x=a;
71             POINT[i].y=b;
72         }
73         double Min=Prim(N);
74         if(Min==-1)printf("oh!\n");
75         else printf("%.1lf\n",100*Min);
76     }
77     return 0;
78 }
View Code

 修改:2015.7.27(快排+并查集)

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <math.h>
  4 #include <algorithm>
  5 #define MAX 1008
  6 using namespace std;
  7 struct poin
  8 {
  9     int x;
 10     int y;
 11     double s;
 12 }Dic[100100];
 13 
 14 int cmp(poin a,poin b)
 15 {
 16     return a.s<b.s;
 17 }
 18 int ID[MAX];
 19 int Sign;
 20 double X[MAX];
 21 double Y[MAX];
 22 double Map[MAX][MAX];
 23 double DIC(double x,double y)
 24 {
 25     return sqrt(x*x+y*y);
 26 }
 27 void Cread(int N)
 28 {
 29     int i,j;
 30     Sign=0;
 31     for(i=0;i<=N;i++)
 32     {
 33         ID[i]=i;
 34         for(j=0;j<=N;j++)
 35             Map[i][j]=MAX;
 36     }
 37 }
 38 
 39 int Find(int x)
 40 {
 41     int TMD;
 42     if(x==ID[x])return x;
 43     else ID[x]=Find(ID[x]);
 44     return ID[x];
 45 }
 46 
 47 void Update(int a,int b)
 48 {
 49     int A,B;
 50     A=Find(a);B=Find(b);
 51     if(A!=B)ID[A]=B;
 52     else Sign++;
 53 }
 54 int main()
 55 {
 56     int T,N,i,j,k,A,B,C,t=1;
 57     double X[MAX],Y[MAX],c;
 58     scanf("%d",&T);
 59     while(T--)
 60     {
 61         scanf("%d",&N);
 62         Cread(N);
 63         for(i=0;i<N;i++)
 64         {
 65             scanf(" %lf %lf",&X[i],&Y[i]);
 66         }
 67         for(i=0;i<N;i++)
 68         {
 69             for(j=0;j<N;j++)
 70             {
 71                 Dic[i*N+j].x=i;
 72                 Dic[i*N+j].y=j;
 73                 if(i==j){Dic[i*N+j].s=MAX;}
 74                 c=DIC(X[i]-X[j],Y[i]-Y[j]);
 75                 if(c<10||c>1000)c=MAX;
 76                 Dic[i*N+j].s=c;
 77             }
 78         }
 79         sort(Dic,Dic+N*N,cmp);
 80         double Sum=0;
 81         int Sign=0;
 82         for(k=0;k<N*N;k++)
 83         {
 84             if(fabs(Dic[k].s-MAX)<=0.00001){Sign=0;break;}
 85             else
 86             {
 87                 A=Find(Dic[k].x);B=Find(Dic[k].y);
 88                 if(A!=B)
 89                 {
 90                     ID[A]=B;
 91                     Sum+=Dic[k].s;
 92                     Sign++;
 93                 }
 94             }
 95             if(Sign==N-1){printf("%.1lf\n",Sum*100);break;}
 96         }
 97         if(Sign!=N-1)printf("oh!\n");
 98     }
 99     return 0;
100 }
View Code
posted @ 2014-08-22 14:08  Wurq  阅读(325)  评论(0编辑  收藏  举报