链接
https://codeforces.com/contest/1198/problem/E
题解
先离散化,把矩形拆成一块一块的
注意离散化有技巧,要用左闭右开区间
然后建一张图,从左往右依次是:源点,行结点,列结点,汇点
一个区块对应的行和列连边流量是无穷,原点向行节点连边,流量是这个行结点对应实际的行数,列结点向汇点连边,流量是这个列结点对应实际的列数
最小割就是答案
代码
#include <bits/stdc++.h>
#define maxn 100010
#define maxe 500010
#define linf (1ll<<60)
#define iinf 0x3f3f3f3f
#define eps 1e-8
#define cl(x) memset(x,0,sizeof(x))
#define mod 998244353ll
using namespace std;
struct Graph2
{
int head[maxn], next[maxe], to[maxe], w[maxe], c[maxe], tot;
void clear(int N)
{
int i;
for(i=1;i<=N;i++)head[i]=0;
for(i=2;i<=tot;i++)next[i]=0;
tot=1;
}
void add(int a, int b, int ww, int cc){to[++tot]=b;next[tot]=head[a];w[tot]=ww;c[tot]=cc;head[a]=tot;}
void adde(int a, int b, int ww,int cc){add(a,b,ww,cc);add(b,a,-ww,0);}
}G;
struct ISAP
{
int S, T, last[maxn], d[maxn], num[maxn], Exit;
void init(int N)
{
for(int i=1;i<=N;i++)d[i]=num[i]=0;
num[0]=N;
Exit=0;
}
int dfs(Graph2& G, int pos, int in)
{
int flow=0, t;
if(pos==T)return in;
for(int &p=last[pos];p;p=G.next[p])
if(G.c[p] and d[G.to[p]]+1==d[pos])
{
flow+= t=dfs(G,G.to[p],min(in-flow,G.c[p]));
G.c[p]-=t, G.c[p^1]+=t;
if(Exit or in==flow)return flow;
}
Exit=--num[d[pos]]==0;
++num[++d[pos]];
last[pos]=G.head[pos];
return flow;
}
int maxflow(Graph2& G)
{
int ans(0);
while(!Exit)ans+=dfs(G,S,iinf);
return ans;
}
}isap;
struct Lisan
{
int tmp[maxn], tot;
void clear(){tot=0;}
void insert(int x){tmp[++tot]=x;}
void run()
{
sort(tmp+1,tmp+tot+1);
tot=unique(tmp+1,tmp+tot+1)-tmp-1;
}
void lisan(int *a, int len)
{
for(int i=1;i<=len;i++)a[i]=lower_bound(tmp+1,tmp+tot+1,a[i])-tmp;
}
int lisan(int x)
{
return lower_bound(tmp+1,tmp+tot+1,x)-tmp;
}
}row, col;
int n, m, X1[maxn], Y1[maxn], X2[maxn], Y2[maxn];
int main()
{
int i, j, k;
cin>>n>>m;
for(i=1;i<=m;i++)
{
cin>>X1[i]>>Y1[i]>>X2[i]>>Y2[i];
row.insert(X1[i]), row.insert(X2[i]+1);
col.insert(Y1[i]), col.insert(Y2[i]+1);
}
row.run(), col.run();
isap.S=row.tot+col.tot+10;
isap.T=isap.S+1;
G.clear(isap.T);
for(i=1;i<row.tot;i++)G.adde(isap.S,i,0,row.tmp[i+1]-row.tmp[i]);
for(i=1;i<col.tot;i++)G.adde(row.tot+i,isap.T,0,col.tmp[i+1]-col.tmp[i]);
for(i=1;i<=m;i++)
{
for(j=row.lisan(X1[i]);row.tmp[j]<X2[i]+1;j++)
for(k=col.lisan(Y1[i]);col.tmp[k]<Y2[i]+1;k++)
G.adde(j,row.tot+k,0,iinf);
}
isap.init(isap.T);
cout<<isap.maxflow(G);
return 0;
}