R的农场

R的农场
题目描述

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

输入

第1 行为三个数 N, M, K。
接下来 N 行为 N 个守卫的位置,每行包含两个实数 x, y (x≥0, y≥0)。
接下来 M 行,每行三个数,u, v, w,代表若平均工资≥w,则 u 和 v 同意和解。

输出

输出文件有且仅有一行,一个实数 p,代表最小的平均工资。

输入输出样例

chebnear.in

5 5 1.300
1.000 1.000
2.000 3.000
3.000 2.000
2.500 6.000
6.000 3.000
2 4 1.500
5 3 2.350
1 4 0.500
4 5 2.250
3 2 3.200

chebnear.out

2.350

反思

本来想用二分答案做到,虽然我确实这么做了,但是由于我没有写完立刻就编译,想着先写后面的再来写,结果......,没有写完,我觉得我写题都要写出毛病来了,每次打完道题目,总有七七八八的东西导致我编译过不了,特别是考试的时候,编译改错要花我好久的时间..

思路

这题的思路其实我还是懂了的

1.我们二分平均工资,把那些权值满足小于等于工资的点之间连上线(其实就是用并查集归类然后再去染色,相当与联通块的染色)

2.我们染色过后,根据最近点对(最近点对就是我们先按x即横坐标排序,求出中线,那么求点之间的最短距离只可能有3种情况1.在中线左边2.在中线右边3.跨过中线相连我们可以先算出2边的最短点对之间的距离,然后我们以这个距离为标准,向左向右分别寻找在该距离之内的点,然后判断就可以了,tips,这个也是递归实现的,因为我们在寻找左右的最短点对时,左右就相当与2个独立的区间,然后我们就在区间内寻找............),我们就可以判断该工资是否合法(如果2给点是相同颜色的,我们就不会更新)

3.最后我们二分寻找答案确定了答案的精度,输出就可以啦!

代码

感觉自己要死了,写了一个晚上,还是木有写出来,我觉得我的思路一点毛病也没有,为什么就是错了!!

先放一份错的,保存一下今天晚上的"成果"!!

OK啦OK啦,我写完啦

我知道为什么我错了!!原来我把题目意思都理解错了!!!!!!!!!我是真心佩服我自己/(ㄒoㄒ)/~~

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define FOR(i,a,b) for(register int i=a;i<=b;i++)
 4 #define ROF(i,a,b) for(register int i=a;i>=b;i--)
 5 using namespace std;
 6 int n,m;
 7 double K;
 8 double maxx=0;
 9 int ans;
10 int fa[100010];
11 int tmpt[100011];
12 struct ss
13 {
14     int x,y;
15     double p;
16 }b[200010];
17 struct ss1
18 {
19     double X,Y;
20     int num;
21 }a[100010],c[100010];
22 int scan()
23 {
24     int as=0,f=1;
25     char c=getchar();
26     while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}
27     while(c>='0'&&c<='9'){as=(as<<3)+(as<<1)+c-'0';c=getchar();}
28     return as*f;
29 }
30 int ba(int x) {return fa[x]=((fa[x]==x)?x:ba(fa[x]));}
31 bool cmp(ss1 i,ss1 j) {return i.X<j.X;}
32 bool cmp2(ss1 i,ss1 j) {return i.Y<j.Y;}
33 bool cmp3(ss i,ss j)   {return i.p<j.p;}
34 bool  clst(int l,int r)
35 {
36     int mid=(l+r)>>1;
37     if(l>=r) return 1;
38     if(!clst(l,mid)||!clst(mid+1,r)) return 0;
39     int k=0;
40     while(a[l].X+K<a[mid].X) l++;
41     while(a[r].X-K>a[mid].X) r--;
42     FOR(i,l,r) c[++k]=a[i];
43     sort(c+1,c+k+1,cmp2);
44     FOR(i,1,k)
45     {
46         FOR(j,i+1,k)
47         {
48             if(c[j].Y-c[i].Y>K) break;
49             if(ba(c[i].num)!=ba(c[j].num))
50             {
51                 if(abs(c[i].X-c[j].X)<=K)
52                     return 0;
53             }
54         }
55     }
56     return 1;
57 }
58 bool chek(int mid)
59 {
60     FOR(i,1,n) fa[i]=i;//父亲的赋值
61     FOR(i,1,m)
62     {
63         if(b[i].p>b[mid].p) break;
64         int f1=ba(b[i].x),f2=ba(b[i].y);//父亲的赋值
65         if(f1!=f2)
66             fa[f1]=f2;
67     }
68     return clst(1,n);
69 }
70 int main()
71 {
72     n=scan();m=scan();
73     scanf("%lf",&K);
74     FOR(i,1,n) scanf("%lf%lf",&a[i].X,&a[i].Y),a[i].num=i;
75     sort(a+1,a+n+1,cmp);//按照X的关键字排序
76     FOR(i,1,m)
77     {
78         b[i].x=scan();b[i].y=scan();scanf("%lf",&b[i].p);
79     }
80     sort(b+1,b+m+1,cmp3);//按照和解费排序
81     int l=0,r=m-1;
82     while(l<=r)
83     {
84         int mid=(l+r)>>1;
85         //cout<<mid<<endl;
86         if(chek(mid))
87         {
88             //        cout<<"NBV"<<" "<<mid<<endl;
89             r=mid-1;
90         }
91         else l=mid+1;
92     }//zh这个二分其实不是很懂...
93 //    cout<<ans-1<<endl;
94     printf("%.3lf",b[l].p);
95 }
96 //找了半天发现是排序的错,我也是佛系了.......
View Code
原文地址:https://www.cnblogs.com/KSTT/p/10370033.html