hdu3228Island Explorer

链接

给你两条线及两条线上的点,求最小生成树。

可以挨个枚举一条线上的点,三分出另一条线上离他最近的点进行连边。

注意N、M可能为0

debug了1天半,至今不知道原始二分版本错在哪里。。

  1 #include <iostream>

  2 #include<cstdio>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<stdlib.h>

  6 #include<vector>

  7 #include<cmath>

  8 #include<queue>

  9 #include<set>

 10 using namespace std;

 11 #define N 50010

 12 #define LL long long

 13 #define INF 0xfffffff

 14 const double eps = 1e-8;

 15 const double pi = acos(-1.0);

 16 const double inf = ~0u>>2;

 17 struct point

 18 {

 19     double x,y;

 20     int id;

 21     point(double x=0,double y = 0):x(x),y(y) {}

 22 } p[N],q[N];

 23 struct node

 24 {

 25     int u,v;

 26     double w;

 27 } ed[N<<4];

 28 int fa[N],g;

 29 double t1[N],t2[N];

 30 point a,b,c,d;

 31 typedef point pointt;

 32 point operator -(point a,point b)

 33 {

 34     return point(a.x-b.x,a.y-b.y);

 35 }

 36 int dcmp(double x)

 37 {

 38     if(fabs(x)<eps) return 0;

 39     return x<0?-1:1;

 40 }

 41 

 42 double dis(point a)

 43 {

 44     return sqrt(a.x*a.x+a.y*a.y);

 45 }

 46 bool cmmp(node ta,node tb)

 47 {

 48     return ta.w<tb.w;

 49 }

 50 int findx(int x)

 51 {

 52     if(x!=fa[x])

 53         fa[x] = findx(fa[x]);

 54     return fa[x];

 55 }

 56 void add(point ta,point tb)

 57 {

 58     ed[++g].u = ta.id;

 59     ed[g].v = tb.id;

 60     ed[g].w = dis(ta-tb);

 61 }

 62 int main()

 63 {

 64     // freopen("data.in","r",stdin);

 65     // freopen("data.out","w",stdout);

 66     int t,i,n,m;

 67     int kk = 0;

 68     cin>>t;

 69     while(t--)

 70     {

 71         scanf("%d%d",&n,&m);

 72         scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&d.x,&d.y);

 73         for(i = 0; i <= n+m ; i++)

 74             fa[i] = i;

 75         for(i = 0; i < n; i++)

 76         {

 77             scanf("%lf",&t1[i]);

 78 

 79             // cout<<p[i].x<<" "<<p[i].y<<endl;

 80         }

 81         for(i = 0; i< m; i++)

 82         {

 83             scanf("%lf",&t2[i]);

 84 

 85         }

 86         sort(t1,t1+n);

 87         sort(t2,t2+m);

 88         int h=0;

 89         for(i=0;i<n;i++)

 90             if(i==n-1||t1[i]!=t1[i+1])

 91                 t1[h++]=t1[i];

 92         n=h;

 93         h=0;

 94         for(i=0;i<m;i++)

 95             if(i==m-1||t2[i]!=t2[i+1])

 96                 t2[h++]=t2[i];

 97         m=h;

 98         for(i = 0; i < n;i++)

 99         {

100              p[i] = point(a.x*t1[i]+b.x*(1-t1[i]),a.y*t1[i]+b.y*(1-t1[i]));

101              p[i].id = i+1;

102         }

103         for(i = 0 ; i < m ; i++)

104         {

105             q[i] = point(c.x*t2[i]+d.x*(1-t2[i]),c.y*t2[i]+d.y*(1-t2[i]));

106             q[i].id = i+n+1;

107         }

108         g = 0;

109         double sum1 = 0,sum2 = 0;

110         for(i = 0 ; i < n-1 ; i++)

111         {

112             add(p[i],p[i+1]);

113             sum1+=dis(p[i]-p[i+1]);

114         }

115         for(i = 0 ; i < m-1 ; i++)

116         {

117             add(q[i],q[i+1]);

118             sum2+=dis(q[i]-q[i+1]);

119         }

120         if(n==0||m==0)

121         {

122 

123             printf("Case #%d: %.3lf\n",++kk,sum1+sum2);

124             continue;

125         }

126         for(i = 0; i < n; i++)

127         {

128 //            point pp ;

129 //            if(dcmp(c.x-d.x)==0)

130 //            pp = point(c.x,p[i].y);

131 //            else

132 //            pp = dispoint(c,d,p[i]);

133 //            if(dcmp(pp.x-min(c.x,d.x))<=0||dcmp(pp.x-max(c.x,d.x))>=0)

134 //            {

135 //                add(i,n+1);

136 //                if(n+2<n+m)

137 //                add(i,n+2);

138 //                if(n+m-1>n+1)

139 //                add(i,n+m-1);

140 //                add(i,n+m);

141 //                continue;

142 //            }

143 //            int k = find(n+1,n+m,c,dis(pp-c));

144             // cout<<p[k].id<<" "<<pp.x<<" "<<pp.y<<endl;

145 //            add(i,k);

146 //            if(k!=n+1)

147 //            add(i,k-1);

148 //            if(k!=n+m)

149 //            add(i,k+1);

150             int l, r;

151             l = 0;

152             r = m-1;

153             while (r - l > 1)

154             {

155                 int mid1 = (r + l) >> 1;

156                 int mid2 = (mid1 + r) >> 1;

157                 if (dis(p[i]-q[mid1]) > dis(p[i]-q[mid2]))

158                     l = mid1;

159                 else

160                     r = mid2;

161             }

162 //            int k = find(1,n,a,dis(pp-a));

163             add(p[i],q[l]);

164             add(p[i],q[r]);

165             if(l-1>=0)

166                 add(p[i],q[l-1]);

167             if(r+1<=m-1)

168                 add(p[i],q[r+1]);

169         }

170         sort(ed+1,ed+g+1,cmmp);

171         int num = 0;

172         double sum = 0;

173         for(i = 1; i <= g; i++)

174         {

175             int tx = findx(ed[i].u);

176             int ty = findx(ed[i].v);

177             if(tx!=ty)

178             {

179                 fa[tx] = ty;

180                 num++;

181                 sum+=ed[i].w;

182             }

183         }

184         printf("Case #%d: %.3f\n",++kk,sum);

185     }

186     return 0;

187 }
View Code

 

你可能感兴趣的:(exp)