Live2d Test Env

洛谷:P1783 海滩防御(二分+并查集 最短路 最小生成树)

题意: 给定长度为N的海滩,然后有M做防御塔,给出每座塔的位置Xi,到海岸的距离Yi。 求防御塔上最小观测半径Ri,使得海滩被封锁。

思路:要使左边界和右边界连通。

很nice,可以二分+并查集做。 可以最小生成树做。 可以最短路做。

MST代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1000010;
double x[maxn],y[maxn],ans; int tot,fa[maxn];
struct in{
    int u,v;
    double len;
}s[maxn];
bool cmp(in w,in p){return w.len<p.len;}
void add(int u,int v,double len)
{
    tot++; s[tot].u=u; s[tot].v=v; s[tot].len=len;
}
int find(int x){
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
int main()
{
    int N,M;
    scanf("%d%d",&N,&M);
    rep(i,1,M) scanf("%lf%lf",&x[i],&y[i]);
    rep(i,0,N+1) fa[i]=i;
    rep(i,1,M) add(0,i,x[i]),add(N+1,i,N-x[i]);
    rep(i,1,M) rep(j,1,M) add(i,j,0.5*sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
    sort(s+1,s+tot+1,cmp);
    rep(i,1,tot){
        int fu=find(s[i].u);
        int fv=find(s[i].v);
        if(fu==fv) continue;
        fa[fu]=fv;
        ans=s[i].len;
        if(find(0)==find(N+1)) break;
    }
    printf("%.2lf\n",ans);
    return 0;
}
View Code

最短路:把常规的路径求和改为路径最大值即可。代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2000010;
double x[maxn],y[maxn],Len[maxn],ans,dis[maxn];
int cnt,Laxt[maxn],Next[maxn],To[maxn],N;bool vis[maxn];
void add(int u,int v,double l)
{
    Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=l;
    Next[++cnt]=Laxt[v]; Laxt[v]=cnt; To[cnt]=u; Len[cnt]=l;
}
void SPFA()
{
    rep(i,1,N+1) dis[i]=0x3f3f3f3f;
    queue<int>q; q.push(0);
    while(!q.empty()){
        int u=q.front(); q.pop(); vis[u]=0;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i]; double t=max(dis[u],Len[i]);
            if(dis[v]>t){
                dis[v]=t;
                if(!vis[v]) q.push(v),vis[v]=1;
            }
        }
    }
}
int main()
{
    int M;
    scanf("%d%d",&N,&M);
    rep(i,1,M) scanf("%lf%lf",&x[i],&y[i]);
    rep(i,1,M) add(0,i,x[i]),add(N+1,i,N-x[i]);
    rep(i,1,M) rep(j,1,M) add(i,j,0.5*sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])));
    SPFA();
    printf("%.2lf\n",dis[N+1]);
    return 0;
}
View Code

 

posted @ 2019-07-10 10:51  nimphy  阅读(270)  评论(0编辑  收藏  举报