三条线_纪中_2929_最大匹配

来源:互联网 发布:深入理解linux内核4.4 编辑:程序博客网 时间:2024/05/22 10:29

题目大意

  为了监视他的N (1 <= N <= 50,000)头奶牛,Farmer John购买了新的监视系统。第i头奶牛位置在(x_i, y_i),坐标为整数,范围0..1,000,000,000。任意两头奶牛的位置不同。   FJ的监视系统有三个摄像头,每个摄像头只能监视一条水平线或者垂直线上的所有奶牛。请计算如果FJ安装好这三个摄像头,能否监视所有的N头奶牛。也就是说,计算N头奶牛的位置,是否可以被三条直线“覆盖”,直线必须是水平线或垂直线。


分析

  最小覆盖问题: 给定一个二分图,求最小的点数,使得每一条边都至少与一个顶点相邻。 

  可以证明:二分图最小覆盖数=最大匹配数。 

  证明:假设最大匹配边数为M。

   1.M是足够的。因为如果存在边E未与顶点相连,则E可以匹配,此时不是最大匹配。 

   2.M是必须的。仅考虑构成最大匹配的M条边,他们两两无公共点,所以需要M个顶点覆盖他们。 

  看不懂?好吧。简而言之,对于i行j列有按钮的格子连边i->j,然后求最大匹配数。

  记得用离散,因为坐标很大。

  我和olahiuj——就是他,

  都想了正解,但是他机(sha)智(bi)的算错了最大匹配数(蜜汁统计错误)。


代码

type  arr=record    x,y,w:longint;    next:longint;end;type  arry=array[0..50001,1..2] of longint;var  a:array[0..50001] of arr;  v:array[0..50001] of boolean;  st,ls:array[0..50001] of longint;  x,y,xy:array[0..50001,1..2] of longint;  i,j:longint;  n,m,nm,n1,m1:longint;  k:char;function find(r:longint):boolean;var  i,j,k:longint;begin  find:=true;  i:=ls[r];  while i<>0 do    begin      with a[i] do        if not v[y]          then            begin              k:=st[y]; st[y]:=r; v[y]:=true;              if (k=0) or find(k) then exit;              st[y]:=k;            end;      i:=a[i].next;    end;  find:=false;end;procedure main;var  i,j,k:longint;  z:boolean;begin  for i:=1 to n1 do    begin      fillchar(v,sizeof(v),0);      z:=find(i);    end;end;procedure add(x,y:longint);begin  nm:=nm+1;  a[nm].x:=x;  a[nm].y:=y;  a[nm].next:=ls[x];  ls[x]:=nm;end;procedure qsort(var a:arry;l,r:longint);var  i,j,k:longint;  mid:longint;  temp:longint;begin  if (l>=r) then exit;  i:=l; j:=r;  mid:=a[(l+r) div 2][1];  repeat    while a[i][1]<mid do i:=i+1;    while a[j][1]>mid do j:=j-1;    if i<=j      then        begin          temp:=a[i][1]; a[i][1]:=a[j][1]; a[j][1]:=temp;          temp:=a[i][2]; a[i][2]:=a[j][2]; a[j][2]:=temp;          i:=i+1; j:=j-1;        end;  until i>j;  qsort(a,l,j);  qsort(a,i,r);end;begin  fillchar(ls,sizeof(ls),0);  fillchar(st,sizeof(st),0);  fillchar(v,sizeof(v),0);  readln(n);  nm:=0;  for i:=1 to n do    begin      readln(x[i][1],y[i][1]);      x[i][2]:=i;      y[i][2]:=i;    end;  qsort(x,1,n);  qsort(y,1,n);  j:=1;  xy[x[1][2]][1]:=j;  for i:=2 to n do    begin      if x[i-1][1]<>x[i][1] then j:=j+1;      xy[x[i][2]][1]:=j;    end;  n1:=j;  j:=1;  xy[y[1][2]][2]:=j;  for i:=2 to n do    begin      if y[i-1][1]<>y[i][1] then j:=j+1;      xy[y[i][2]][2]:=j;    end;  m1:=j;  for i:=1 to n do    add(xy[i][1],xy[i][2]);  main;  j:=0;  for i:=1 to m1 do    if st[i]<>0 then j:=j+1;  if j<=3    then write(1)    else write(0);end.


2 0
原创粉丝点击