题面:Luogu3033
我们把横着的线段分一组,竖着的线段分一组
然后把相交的线段连边即可
这样就形成了一个二分图
然后要说一下两个东西:
- 二分图最小点覆盖:定义一个点能够覆盖以之为端点的所有边,定义点覆盖为覆盖图所有边的点集,最小点覆盖即为包含点数尽量少的点集。
- 二分图最大独立集:独立集是两两没有公共边的点集,最大独立集即为点数尽量多的独立集。
很明显这题要求的是二分图的最大独立集
那么如何求这个独立集呢?
这里又有两个定理:
- 二分图的最大独立集等于二分图最小点覆盖关于全点集的补集。
- 二分图的最大匹配集合数值上等于最小点覆盖的大小。
为什么呢,(自己yy)很好理解,首先第一个画画图就可以得出了,第二个也很显然,把所有连接最小点覆盖点集的边搞掉之后剩下的点肯定没有公共边
于是我们就可以直接Hungary或者网络流求解了
dinic:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdlib>
#include<string>
#include<ctime>
#include<queue>
#include<climits>
using namespace std;
int n,m,s,t,xx[1001],xy[1001],dx[1001],dy[1001];
int dist[100001],nedge=-1,head[200001],nex[200001],p[200001],c[200001];
inline void addedge(int x,int y,int z){
p[++nedge]=y;c[nedge]=z;nex[nedge]=head[x];head[x]=nedge;
}
inline bool bfs(int s,int t){
queue<int>q;q.push(s);
memset(dist,-1,sizeof dist);dist[s]=1;
while(!q.empty()){
int now=q.front();q.pop();
for(int k=head[now];k>-1;k=nex[k])if(c[k]&&dist[p[k]]==-1){
dist[p[k]]=dist[now]+1;q.push(p[k]);
}
}
return dist[t]>-1?1:0;
}
inline int dfs(int x,int low){
if(x==t)return low;
int a,used=0;
for(int k=head[x];k>-1;k=nex[k])if(c[k]&&dist[p[k]]==dist[x]+1){
a=dfs(p[k],min(low-used,c[k]));
if(a)c[k]-=a,c[k^1]+=a,used+=a;
if(used==low)break;
}
if(!used)dist[x]=-1;
return used;
}
inline int dinic(){
int flow=0;
while(bfs(s,t))flow+=dfs(s,1e9);
return flow;
}
inline void check(int x,int y){//判断是否相交
if(xx[x]==dx[x]&&xx[y]==dx[y])return;
if(xy[x]==dy[x]&&xy[y]==dy[y])return;
if(xx[x]==dx[x]){
if(xy[y]>=xy[x]&&xy[y]<=dy[x]&&xx[x]>=xx[y]&&xx[x]<=dx[y])addedge(x,y,1),addedge(y,x,0);
}else{
if(xy[x]>=xy[y]&&xy[x]<=dy[y]&&xx[y]>=xx[x]&&xx[y]<=dx[x])addedge(y,x,1),addedge(x,y,0);
}
}
int main()
{
memset(p,-1,sizeof p);memset(nex,-1,sizeof nex);
memset(c,-1,sizeof c);memset(head,-1,sizeof head);
scanf("%d",&n);
s=0;t=n+1;
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&xx[i],&xy[i],&dx[i],&dy[i]);
if(xx[i]>dx[i])swap(xx[i],dx[i]);if(xy[i]>dy[i])swap(xy[i],dy[i]);
if(xx[i]==dx[i])addedge(s,i,1),addedge(i,s,0);
else if(xy[i]==dy[i])addedge(i,t,1),addedge(t,i,0);
for(int j=1;j<i;j++)check(j,i);
}
printf("%d",n-dinic());
return 0;
}