2017年8月14日提高组T1 跳跃

Description


在平面直角坐标系内有n个点。现在有m个人,每个人都有一个行走距离d,也就是说这个人只能走到与它当前位置距离不大于d的点。问有多少个人可以从任意一个点开始,并能够到达所有点。

Input


第一行为一个整数m,表示人的个数。
第二行为m个整数d,表示每个人的行走距离。
第三行为一个数n,表示点的数量。
接下来n行每行包含两个整数x,y,表示平面内一个点的坐标。

Output


一行一个整数表示答案。

Hint


对于40%的数据,2<=n<=100,1<=m<=100
对于100%的数据,2<=n<=1000,1<=m<=500,1<=d<=1000,-1000<=x,y<=1000

Source


BY BPM

Solution


题意看错,语文水平有待提高

一个人肯定通过最短路走完全程,那么考虑最小生成树。找到最小生成树中的最长边剔除掉不符合的即可。

据说水法暴力求最短距离去掉走不完最短距离的人可以80’

Code


#include <stdio.h>
#include <string.h>
#include <queue>
#include <vector>
#include <math.h>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define erg(i, st) for (int i = ls[st]; i; i = e[i].next)
#define fill(x, t) memset(x, t, sizeof(x))
#define max(x, y) (x)>(y)?(x):(y)
#define min(x, y) (x)<(y)?(x):(y)
#define ll long long
#define db double
#define INF 0x3f3f3f3f
#define N 1001
#define E N * N + 1
#define L 256
struct edge{int x, y, w;}e[E];
struct pos{int x, y;}p[N];
int fa[N], v[N];
inline int read(){
    int x = 0, v = 1; char ch = getchar();
    while (ch < '0' || ch > '9'){if (ch == '-'){v=-1;}ch=getchar();}
    while (ch <= '9' && ch >= '0'){x = x * 10 + ch - '0'; ch = getchar();}
    return x*v;
}
inline int getFather(int now){return (fa[now] == now)?now:fa[now] = getFather(fa[now]);}
inline int dis(pos a, pos b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
inline bool merge(int x, int y){
    int fx = getFather(x);
    int fy = getFather(y);
    if (fx == fy){return 0;}
    fa[fx] = fy;
    return 1;
}
inline bool cmp(edge a, edge b){return a.w < b.w;}
int main(void){
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    int edgeCnt = 0;
    int n = read();
    rep(i, 1, n){v[i] = read();}
    int m = read();
    rep(i, 1, m){p[i].x = read(); p[i].y = read(); fa[i] = i;}
    rep(i, 1, m){
        rep(j, 1, i-1){
            int d = dis(p[i], p[j]);
            e[++edgeCnt]=(edge){i, j, d};
        }
    }
    std:: sort(e + 1, e + edgeCnt + 1, cmp);
    int cnt = 0;
    int len = 0;
    rep(i, 1, edgeCnt){
        if (merge(e[i].x, e[i].y)){
            cnt += 1;
            len = e[i].w;
        }
        if (cnt == m - 1){break;}
    }
    int ans = 0;
    rep(i, 1, n){ans += (v[i]*v[i] >= len);}
    printf("%d\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值