bzoj4080

分组赛时wy大神讲的题,网上都是随机化的题解

我来讲一下正解吧,我们穷举两个点,这两点距离要小于限制

然后我们分别以这两个点为圆心,两点距离为半径画圆

圆圆相交的部分被两点练成线段划分成两部分,不难发现

每个部分内点点之间的距离是小于限制的,很明显想到二分图

对于上半部分与下半部分的两点,如果距离大于限制则连边

然后我们求最大点独立集即可

求最大独立集的方案各种想错,实在太SB

做完最大匹配后首先先把未匹配的点拉出来,然后把他们有边相连的点都标记

然后处理每对匹配,若一个点被标记则选另一个点

这样是不可能出现两个点都标记的匹配,因为这样就会出现一条增广路,与最大匹配矛盾

type node=record
       po,next:longint;
     end;

var e,ee:array[0..10010] of node;
    q,q1,q2,c,x,y,cy,cx,p:array[0..110] of longint;
    v,v1,v2:array[0..110] of boolean;
    z,ll,d,t1,t2,i,j,k,l,ans,len,n:longint;

procedure add(x,y:longint);
  begin
    inc(len);
    e[len].po:=y;
    e[len].next:=p[x];
    p[x]:=len;
    ee[len].po:=x;
    ee[len].next:=q[y];
    q[y]:=len;
  end;

function dfs(x:longint):longint;
  var i,y:longint;
  begin
    i:=p[x];
    while i<>0 do
    begin
      y:=e[i].po;
      if not v[y] then
      begin
        v[y]:=true;
        if (cy[y]=-1) or (dfs(cy[y])=1) then
        begin
          cy[y]:=x;
          cx[x]:=y;
          exit(1);
        end;
      end;
      i:=e[i].next;
    end;
    exit(0);
  end;

function match:longint;
  var i:longint;
  begin
    fillchar(cy,sizeof(cy),255);
    fillchar(cx,sizeof(cx),255);
    match:=t1+t2;
    if (t2=0) or (t1=0) then exit;
    for i:=1 to t1 do
      if cx[i]=-1 then
      begin
        fillchar(v,sizeof(v),false);
        match:=match-dfs(i);
      end;
  end;

function cross(i,j,k:longint):longint;
  begin
    exit((x[i]-x[k])*(y[j]-y[k])-(x[j]-x[k])*(y[i]-y[k]));
  end;

function dis(i,j:longint):longint;
  begin
    exit(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
  end;

begin
  readln(n,d);
  d:=d*d;
  for i:=1 to n do
    readln(x[i],y[i]);
  ans:=1;
  c[1]:=1;
  for i:=1 to n-1 do
    for j:=i+1 to n do
      if dis(i,j)<=d then
      begin
        ll:=dis(i,j);
        t1:=0;
        t2:=0;
        fillchar(p,sizeof(p),0);
        fillchar(q,sizeof(q),0);
        len:=0;
        for k:=1 to n do
          if (dis(i,k)<=ll) and (dis(j,k)<=ll) then
          begin
            if cross(k,j,i)>=0 then
            begin
              inc(t1);
              q1[t1]:=k;
            end
            else begin
              inc(t2);
              q2[t2]:=k;
            end;
          end;
        for k:=1 to t1 do
          for l:=1 to t2 do
            if dis(q1[k],q2[l])>d then add(k,l);

        l:=match;
        if l>ans then
        begin
          ans:=0;
          fillchar(v1,sizeof(v1),false);
          fillchar(v2,sizeof(v2),false);
          for k:=1 to t1 do
            if cx[k]=-1 then
            begin
              inc(ans);
              c[ans]:=q1[k];
              z:=p[k];
              while z<>0 do
              begin
                v2[e[z].po]:=true;
                z:=e[z].next;
              end;
            end;

          for k:=1 to t2 do
            if cy[k]=-1 then
            begin
              inc(ans);
              c[ans]:=q2[k];
              z:=q[k];
              while z<>0 do
              begin
                v1[ee[z].po]:=true;
                z:=ee[z].next;
              end;
            end;

          for k:=1 to t1 do
            if cx[k]<>-1 then
            begin
              inc(ans);
              if not v1[k] then c[ans]:=q1[k]
              else c[ans]:=q2[cx[k]];
            end;
        end;
      end;
  writeln(ans);
  for i:=1 to ans do
    write(c[i],‘ ‘);
  writeln;
end.

时间: 2024-08-26 23:34:35

bzoj4080的相关文章

【BZOJ4080】[Wf2014]Sensor Network 随机化

[BZOJ4080][Wf2014]Sensor Network Description 魔法炮来到了帝都,除了吃特色菜之外,还准备去尝一尝著名的北京烤鸭.帝都一共有n(1<=1<=100)个烤鸭店,可以看成是二维平面内的点.不过由于魔法炮在吃烤鸭之前没有带钱,所以吃完烤鸭之后只能留下刷盘子.刷完盘子之后,魔法炮除了不用付饭费之外,老板还会奖励他d(1<=d<=10000)元钱.魔法炮是一个特么喜欢吃烤鸭的孩子,所以在去过一家烤鸭店之后,魔法炮还准备去其他的烤鸭店.但是由于帝都路费

【BZOJ4080】【WF2014】Sensor Network [随机化]

Sensor Network Time Limit: 2 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 魔法炮来到了帝都,除了吃特色菜之外,还准备去尝一尝著名的北京烤鸭. 帝都一共有n个烤鸭店,可以看成是二维平面内的点. 不过由于魔法炮在吃烤鸭之前没有带钱,所以吃完烤鸭之后只能留下刷盘子. 刷完盘子之后,魔法炮除了不用付饭费之外,老板还会奖励他d元钱. 魔法炮是一个特么喜欢吃烤鸭的孩子,所以在去过一家烤鸭店之后,魔法

【随机化】bzoj4080 [Wf2014]Sensor Network

#include<cstdio> #include<algorithm> #include<cmath> using namespace std; typedef double db; struct Point{int x,y,p;}p[101],path[101]; int n,m,ans,apa[101]; int sqr(int x){return x*x;} int dis(Point a,Point b){return sqr(a.x-b.x)+sqr(a.y