【杭电多校2020】Go Running【几何】【最小点覆盖】

题意:有一个数轴,若干人在某个时刻开始从某个点朝某个方向按 1 1 1的速度走若干时间。已知 n n n个条件,形如 t i t_i ti时刻 x i x_i xi的位置有人,求最少可能的人数。

∑ n ≤ 5 × 1 0 5 \sum n\leq 5\times 10^5 n5×105

画出 x − t x-t xt二维平面,可以看成用最少 k = ± 1 k=\pm1 k=±1的直线覆盖给出的 n n n个点

45 ° 45\degree 45°看成水平线或竖直线(但好像没啥区别)

过每个点作水平线和竖直线,将直线去重,然后直线建成点,点建成过它作的两个直线之间连的边,跑最小点覆盖即可。

注意匈牙利是 O ( n m ) O(nm) O(nm),dinic只有 O ( m n ) O(m\sqrt n) O(mn )

#include 
#include 
#include 
#include 
#include 
#define MAXN 200005
#define MAXM 400005
#define INF 0x3f3f3f3f
using namespace std;
struct edge{int u,v,c;}e[MAXM];
int head[MAXN],nxt[MAXM],cnt;
void ins(int u,int v,int c)
{
	e[++cnt]=(edge){u,v,c};
	nxt[cnt]=head[u];
	head[u]=cnt;
}
void addnode(int u,int v,int c){ins(u,v,c);ins(v,u,0);}
int s,t;
int dis[MAXN];
bool bfs()
{
	queue<int> q;
	q.push(s);
	memset(dis,-1,sizeof(dis));
	dis[s]=0;
	while (!q.empty())
	{
		int u=q.front();
		q.pop();
		for (int i=head[u];i;i=nxt[i])
			if (e[i].c&&dis[e[i].v]==-1)
			{
				dis[e[i].v]=dis[u]+1;
				q.push(e[i].v);
				if (e[i].v==t)
					return true;
			}
	}
	return false;
}
int dfs(int u,int f)
{
	if (u==t||!f)
		return f;
	int used=0;
	for (int i=head[u];i;i=nxt[i])
		if (e[i].c&&dis[e[i].v]==dis[u]+1)
		{
			int w=dfs(e[i].v,min(e[i].c,f));
			if (!w)
				continue;
			used+=w;
			e[i].c-=w;
			e[i^1].c+=w;
			f-=w;
			if (used==0)
				break;
		}
	if (!used) dis[u]=-1;
	return used;
}
int dinic()
{
	int mflow=0;
	while (bfs())
		mflow+=dfs(s,INF);
	return mflow;
}
int x[MAXN],y[MAXN],xl[MAXN],yl[MAXN],xcnt,ycnt;
int main()
{
	int T;
	scanf("%d",&T);
	while (T--)
	{
		int n;
		scanf("%d",&n);
		for (int i=1;i<=xcnt+ycnt+2;i++) head[i]=0;
		for (int i=1;i<=cnt;i++) nxt[i]=0;
		cnt=1,xcnt=ycnt=0;
		for (int i=1;i<=n;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			x[i]=xl[i]=a+b;
			y[i]=yl[i]=a-b;
		}
		sort(xl+1,xl+n+1);
		xcnt=unique(xl+1,xl+n+1)-xl-1;
		sort(yl+1,yl+n+1);
		ycnt=unique(yl+1,yl+n+1)-yl-1;
		s=xcnt+ycnt+1,t=s+1;
		for (int i=1;i<=xcnt;i++) addnode(s,i,1);
		for (int i=xcnt+1;i<=xcnt+ycnt;i++) addnode(i,t,1);
		for (int i=1;i<=n;i++)
		{
			x[i]=lower_bound(xl+1,xl+xcnt+1,x[i])-xl;
			y[i]=lower_bound(yl+1,yl+ycnt+1,y[i])-yl;
			addnode(x[i],y[i]+xcnt,1);
		}
		printf("%d\n",dinic());
	}
	return 0;
}

你可能感兴趣的:(【杭电多校2020】Go Running【几何】【最小点覆盖】)