JZOJ 5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven

题目

JZOJ 5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven_第1张图片

题解

这题可以二分,设答案为mid,将问题转化为纵坐标为[mid,m-mid]之间的,点变成半径为mid的圆,看上面是否能连到下面。
80分:并查集做法。(然而我是这么做的,我直接存储该圆与哪一边连通,如果一个圆既与上面连通,又与下面连通,那么mid过大,我不知道这么做为什么是错的,有大佬帮我看看为什么吗?我WA了3个点)(第一份代码是WA了的代码)
100分做法:不二分,考虑连最小生成树。k+2个点,但是很多条边。所以用Prim算法。然后答案即为k+1到k+2的路径上最长边/2。
Prim算法:设Dis[i]表示目前没有被选的点i与任何一个被选的点的最小距离。
然后每一次挑选一个Dis最小的点作为下一个被选的点。

AC代码

#include
#include
#include
#include
#include
#define N 1000010
#define eps 0.0000005
#define DB double
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
struct point{
    DB x,y; 
};point pt[N];
int n,m,k;
int i,j;
DB l,r,l1,r1,mid,ans,temp;
int bel[N];
bool jie;
bool cmp(point a,point b){
    return a.yreturn sqrt((X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2));
}
int main(){
    freopen("starway.in","r",stdin);
    freopen("starway.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    fo(i,1,k)scanf("%lf%lf",&pt[i].x,&pt[i].y);
    sort(pt+1,pt+k+1,cmp);
    ans=0;
    l=0,r=(DB)m/2;
    while(l<=r){
        mid=(l+r)/2;
        l1=mid;r1=m-mid;
        memset(bel,0,sizeof(bel));
        fo(i,1,k)
            if(pt[i].y<=l1+mid) bel[i]=1;else break;
        fd(i,k,1)
            if(pt[i].y>=r1-mid) bel[i]=2;else break;
        jie=0;
        fo(i,1,k-1){
            if(bel[i]==1){
                fo(j,i+1,k){
                    temp=dis(pt[i].x,pt[i].y,pt[j].x,pt[j].y);
                    if(temp<=2*mid){
                        if(bel[j]==2){
                            jie=1;
                            break;
                        }
                        bel[j]=1;
                    }
                }
            }
            if(jie)break;
        }
        if(jie)r=mid-eps;else ans=mid,l=mid+eps;
    }
    printf("%.8lf",ans);
    return 0;
}
#include
#include
#include
#include
#include
#define N 6010
#define eps 0.000001
#define DB double
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
struct point{
    DB x,y;
};point pt[N];
struct note{
    int to,next;
    DB val;
};note edge[N*2];
int n,m,k,tot;
int i,j,gx,gy,wz,x;
DB l,r,l1,r1,mid,ans,mx,temp;
DB a1,a2,a3,a4;
int a[N][5],f[N];
DB dis[N];
int head[N],pre[N];
bool jie[N],vis[N],p;
int read(){
    int res=0,fh=1;char ch;
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')fh=-1,ch=getchar();
    while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();
    return res;
}
void lb(int x,int y,DB z){
    edge[++tot].to=y;
    edge[tot].next=head[x];
    edge[tot].val=z;
    head[x]=tot;
}
DB getdis(int a,int b){
    if(a>b)swap(a,b);
    if(a==k+1&&b==k+2)return m;
    if(b==k+1)return pt[a].y;
    if(b==k+2)return m-pt[a].y;
    return sqrt((pt[a].x-pt[b].x)*(pt[a].x-pt[b].x)+(pt[a].y-pt[b].y)*(pt[a].y-pt[b].y));
}
int get(int x){return(f[x]==x)?x:f[x]=get(f[x]);}
void dg(int x,int fa,DB v){
    if(x==k+2){
        ans=v;
        return;
    }
    int i;
    for(i=head[x];i;i=edge[i].next)
        if(edge[i].to!=fa)dg(edge[i].to,x,max(v,edge[i].val));
}
int main(){
    freopen("starway.in","r",stdin);
    freopen("starway.out","w",stdout);
    n=read();m=read();k=read();
    fo(i,1,k){
        gx=read();gy=read();
        pt[i].x=(DB)gx;pt[i].y=(DB)gy;
    }
    ans=0;
    memset(dis,127,sizeof(dis));
    dis[k+1]=0;
    fo(i,1,k+2){
        wz=0,mx=2147483647;
        fo(j,1,k+2)
            if(dis[j]if(pre[wz])lb(pre[wz],wz,dis[wz]),lb(wz,pre[wz],dis[wz]);
        vis[wz]=1;
        fo(j,1,k+2)
            if(!vis[j] && wz!=j){
                temp=getdis(wz,j);
                if(temp1,0,0);
    ans/=2;
    printf("%.8lf",ans);
    return 0;
}

你可能感兴趣的:(JZOJ 5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven)