• 「模拟8.17」star way to heaven(并查集,最小生成树)


    80分打法

    首先二分最后答案,答案即为r,可看作以每个k为圆心r为半径的圆

    我们进行并查集维护,维护相交的圆的边界

    最后判断是否存在圆将上下边界覆盖,如有证明不行

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<string>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 #define min(a,b) a>b?b:a
    11 #define max(a,b) a>b?a:b
    12 #define int long long 
    13 #define MAXN 1000001
    14 using namespace std;
    15 int fa[MAXN];
    16 double l_y[MAXN],r_y[MAXN];
    17 int x[MAXN],y[MAXN];
    18 int find(int x)
    19 {
    20      if(fa[x]==x)return fa[x];
    21      return fa[x]=find(fa[x]);
    22 }
    23 bool judge(int xx,int yy,double r)
    24 {
    25      double deta_x=abs(x[xx]-x[yy]);
    26      double deta_y=abs(y[xx]-y[yy]);
    27      //printf("deta_x=%lld deta_y=%lld
    ",deta_x,deta_y);
    28      if((double)deta_x*deta_x+(double)deta_y*deta_y<(2.0*r)*(r*2.0))return 1;
    29      return 0;
    30 }
    31 int n,m,k;
    32 bool work(double cir)
    33 {
    34      for(int i=1;i<=k;++i)fa[i]=i;
    35      for(int i=1;i<=k;++i)
    36      {
    37          l_y[i]=(double)y[i]-cir;r_y[i]=(double)y[i]+cir;
    38      }
    39      for(int i=1;i<=k;++i)
    40      {
    41          for(int j=1;j<=k;++j)
    42          {
    43              //printf("i=%lld j=%lld
    ",i,j);
    44              int xx=find(i);int yy=find(j);
    45              if(xx==yy)continue;
    46              if(judge(i,j,cir))
    47              {
    48                 fa[yy]=xx;
    49                 l_y[yy]=l_y[xx]=min(l_y[yy],l_y[xx]);
    50                 r_y[yy]=r_y[xx]=max(r_y[yy],r_y[xx]);    
    51                 //printf("l_y[%lld]=%.4lf r_y[%lld]=%.4lf
    ",xx,l_y[xx],xx,r_y[xx]);            
    52              }
    53          }
    54      }
    55      for(int i=1;i<=k;++i)
    56      {
    57          if(l_y[find(i)]<cir&&r_y[find(i)]>m-cir)
    58          {
    59              //printf("l_y[%lld]=%.4lf r_y[%lld]=%.4lf
    ",find(i),l_y[find(i)],find(i),r_y[find(i)]);            
    60              return 0;
    61          }
    62      }
    63      return 1;
    64 }
    65 void second_divided()
    66 {
    67      double l=0.0,r=m;
    68      while(l+0.0000001<r)
    69      {
    70            double mid=(l+r)/2;
    71            //printf("mid=%.4lf
    ",mid);
    72            if(work(mid))
    73            {
    74               l=mid;
    75            }
    76            else r=mid;
    77      }
    78      if(work(r))printf("%.6lf
    ",r);
    79      else printf("%.6lf
    ",l);
    80 }
    81 signed main()
    82 {
    83      scanf("%lld%lld%lld",&n,&m,&k);
    84      for(int i=1;i<=k;++i)scanf("%lld%lld",&x[i],&y[i]);
    85      second_divided();
    86 }
    View Code

    100分

    开始是很难看出这是最小生成树,(听说是什么欧几里得最小生成树,非常神奇)

    对于最小生成树有几个性质:(自己瞎写的,可能不对)

    1.最小生成树包含两点之间路径的最小边

    2.最小生成树生成的边和最小

    对于此题,我们尽量选边权小的边,构成最小生成树,

    选出从上边界到下边界的最大边权,除二既是答案

    最小生成树保证了选出这个边后,其他圆只会离他更远,所以正确

    另外学习了prim算法

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<string>
     7 #include<vector>
     8 #include<map>
     9 #include<set>
    10 #define min(a,b) a>b?b:a
    11 #define max(a,b) a>b?a:b
    12 #define int long long 
    13 #define MAXN 1000001
    14 using namespace std;
    15 double disx[MAXN],disy[MAXN];
    16 int n,m,k;
    17 double d[MAXN];int vis[MAXN];int fa[MAXN];
    18 double poww(double x)
    19 {
    20     return x*x;
    21 }
    22 struct no{int to,n;double w;}e[MAXN*2];int head[MAXN],tot;
    23 void add(int u,int v,double w)
    24 {
    25      e[++tot].to=v;e[tot].n=head[u];e[tot].w=w;head[u]=tot;
    26 }
    27 double cal(int x,int y)
    28 {
    29     if(x>y)swap(x,y);
    30     if(x==k+1&&y==k+2)return (double)m;
    31     if(y==k+1)return disy[x];
    32     if(y==k+2)return (double)m-disy[x];
    33     //printf("cal%.4lf
    ",sqrt(poww(disx[x]-disx[y])+poww(disy[x]-disy[y])));
    34     return sqrt(poww(disx[x]-disx[y])+poww(disy[x]-disy[y]));
    35 }
    36 void prim()
    37 {
    38      memset(vis,0,sizeof(vis));
    39      for(int i=1;i<=k+2;++i)d[i]=100000000000.0;
    40      d[1]=0;
    41      for(int i=1;i<k+2;++i)
    42      {
    43          double minn=100000000000.0;int x=0;
    44          for(int j=1;j<=k+2;++j)
    45          {
    46              if(!vis[j]&&d[j]<minn)
    47              {
    48                   minn=d[j];x=j;
    49              }
    50          }
    51          vis[x]=1;
    52          for(int j=1;j<=k+2;++j)
    53          {
    54              if(!vis[j])
    55              {
    56                 double dis=cal(x,j);
    57                 if(dis<d[j])
    58                 {
    59                     d[j]=dis;
    60                     fa[j]=x;
    61                     //printf("j=%lld x=%lld dis=%.4lf
    ",j,x,d[j]);
    62                 }
    63              }
    64          }
    65      }
    66      for(int i=2;i<=k+2;++i)
    67      {
    68          add(i,fa[i],d[i]);add(fa[i],i,d[i]);
    69          //printf("%lld %lld %.4lf
    ",fa[i],i,d[i]);
    70      }
    71 }
    72 double ans=0.0;
    73 void DFS(int x,double w,int fa)
    74 {
    75      if(x==k+2){ans=w;return ;}
    76      for(int i=head[x];i;i=e[i].n)
    77      {
    78          int to=e[i].to;
    79          if(to==fa)continue;
    80          DFS(to,max(w,e[i].w),x);
    81      }
    82 }
    83 signed main()
    84 {
    85     scanf("%lld%lld%lld",&n,&m,&k);
    86     for(int i=1;i<=k;++i)
    87     {
    88         scanf("%lf%lf",&disx[i],&disy[i]);
    89     }
    90     prim();
    91     DFS(k+1,0,0);
    92     printf("%.7lf
    ",ans/2);
    93 }
    View Code
  • 相关阅读:
    一个由“ YYYYMMdd ”引发的惨案 !元旦来临前的警惕
    elasticJob 自定义任务参数
    java 生成GUID
    java ArrayList和LinkedList的区别
    Linux下配置python Jupyter远程访问
    《Go并发编程实战》系列二:多线程编程
    《Go并发编程实战》系列一:多进程编程
    《Go并发编程实战》学习基础
    归并排序递归方式和非递归(Java)
    滕讯一面总结
  • 原文地址:https://www.cnblogs.com/Wwb123/p/11370472.html
Copyright © 2020-2023  润新知