zoukankan      html  css  js  c++  java
  • R的农场 chebnear

       评测传送门

    Description
    最近,R 终于获得了一片他梦寐以求的农场,但如此大的一片农场,想要做好防卫工作可不是一件容易的事。所以 R 购买了 N 个守卫,分别让他们站在一定的位置上(守卫不可移动,同一位置上至多有一个守卫)。但是,安排了所有的守卫之后,R 才发现,守卫们彼此十分厌恶。经 R 研究,当某两个守卫距离≤K,他们就会发生争吵;但是,想要守卫们和解也是不难的——只需要 R 给出的平均工资能使两人满意,他们就会同意和解、成为朋友;当然,如果两个守卫有共同的朋友,他们也会和解成为朋友。R 非常不想守卫们争吵,因此他想找出,在能使所有守卫闭嘴的前提下,平均工资的最小值是多少。

    他想到了一个绝妙的方法,但他忙着去 Farm,没时间,所以这个任务就交给你了。
    Input
    第 1 行为三个数 N, M, K。
    接下来 N 行为 N 个守卫的位置,每行包含两个实数 x, y (x≥0, y≥0)。
    接下来 M 行,每行三个数,u, v, w,代表若平均工资≥w,则 u 和 v 同意和解。
    Output
    输出文件有且仅有一行,一个实数 p,代表最小的平均工资。

    data range

    M≤100000, M≤200000

    Attention
    1、本题中的距离定义:对于两个守卫 (x1, y1), (x2, y2) ,它们的距离定义为 max{|x1-x2|,|y1-y2|} 。
    2、整数均在 int 范围内,实数均在 double 范围内。
    3、给定图中可能存在重边。
    4、输出结果保留三位小数。

    25分思路:

      预处理出发生冲突的守卫编号

      然后依据输入的两个守卫成为friends的最低平均工资连边

      边权即为输入的最低工资

      然后枚举之前预处理出的发生冲突的守卫 求出它们之间的最短路

      这里路长的定义为:经过的所有路径的边权的最大值,而不是所有路径边权相加

      在所有的最短路之间取max即可

     

    正解思路:

      枚举最低平均工资

      发现它可以二分 即若当前最低平均工资满足所有守卫无冲突

      则 r=mid-1寻找更小的 反之....

      二分工资之后怎么判断是否符合题意呢:

      若两个守卫成为朋友的最低工资<=mid 那么连边(用并查集就可以了)

      然后求平面内最近点对(连了线的两点不对答案做贡献)   (这里是最近点对qwq)

      若最近点对之间的距离>k则合题意

    我觉得上面辣种求最近点对的思路很好但是我调了很久的code还没好

    然后又借鉴了一下wch的想法   我发现也很好啊不用求最近点对了

    也是分治 找有没有两点之间的距离小于等于k 直接在solve里面判断

    CODE:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cmath>
     5 #define R register
     6 #define go(i,a,b) for(R int i=a;i<=b;i++)
     7 #define M 100001
     8 #define db double
     9 #define inf 210000000.0
    10 using namespace std;
    11 struct node1{db x,y;int id;}a[M],c[M];
    12 struct node2{int u,v;db w;}b[M<<1];
    13 int n,m,f[M];
    14 db k;
    15 int find(int x){if(f[x]==x)return x;return f[x]=find(f[x]);}
    16 bool cmp1(node2 x,node2 y){return x.w<y.w;}
    17 bool cmp2(node1 x,node1 y){return x.y<y.y;}
    18 bool cmp3(node1 x,node1 y){return x.x<y.x;}
    19 bool sol(int l,int r)
    20 {
    21     if(l>=r) return 1;//边界
    22     int mid=(l+r)>>1,ct=0;
    23     if(!sol(l,mid)||!sol(mid+1,r)) return 0;
    24     while(a[l].x+k<a[mid].x) l++;
    25     while(a[r].x-k>a[mid].x) r--;
    26     go(i,l,r) c[++ct]=a[i];
    27     sort(c+1,c+ct+1,cmp2);
    28     go(i,1,ct)
    29         go(j,i+1,ct)
    30     {
    31         if(c[j].y-c[i].y>k) break;
    32         if(fabs(c[i].x-c[j].x)<=k&&find(c[i].id)!=find(c[j].id)) return 0;
    33         //这里只要判断x 因为已经保证 c[j].y-c[i].y<=k
    34     }
    35     return 1;
    36 }
    37 bool ck(int mid)
    38 {
    39     go(i,1,n) f[i]=i; //不要落掉这一步啦 写并查集的时候一定要记得!
    40     go(i,1,m)
    41     {
    42         if(b[i].w>b[mid].w) break;
    43         f[find(b[i].u)]=find(b[i].v);//注意这里啊 开始写错了找了好久qwq
    44     }
    45     return sol(1,n);
    46 }
    47 int main()
    48 {
    49     cin>>n>>m>>k;
    50     go(i,1,n) cin>>a[i].x>>a[i].y,a[i].id=i;
    51     sort(a+1,a+n+1,cmp3);//按x排序
    52     go(i,1,m) cin>>b[i].u>>b[i].v>>b[i].w;
    53     sort(b+1,b+m+1,cmp1);//按w排序
    54     //好像很少写对过二分??初始化 mid+-1什么的总是搞错
    55     //然后这题的二分还不清楚为什么我之前写的不对 要去问一下 然后再写到这里来
    56     int l=0,r=m-1,mid;//这里要注意l,r的初始化
    57     while(l<=r)
    58     {
    59         mid=(l+r)>>1;
    60         if(ck(mid)) {r=mid-1;}
    61         else l=mid+1;
    62     }
    63     printf("%.3lf",b[l].w);
    64     return 0;
    65 }
    View Code
    光伴随的阴影
  • 相关阅读:
    Kubernetes中Pod之间使用虚拟二层网络连接
    ResourceQuota和LimitRange实践指南
    Namespace集群环境的共享与隔离
    K8s生产架构
    K8s常用命令整理+名词解析
    K8s中的pv&&pvc
    Kubernetes保证集群内节点和网络安全
    Kubernetes中网络相关知识
    kubectl常用命令
    物理ceph集群+K8s
  • 原文地址:https://www.cnblogs.com/forward777/p/10360057.html
Copyright © 2011-2022 走看看