三条线_纪中_2929_最大匹配
题目大意
为了监视他的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.