题目大意
为了监视他的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.