http://acm.hdu.edu.cn/showproblem.php?pid=6808
画一个t为x轴,x为y轴的坐标系,由于每个人的速度都是1m/s
那么如果两个点是一个人,那么就要么斜率为1,要么斜率为-1,
这就转换为了经典二分图匹配模型,一个棋盘,要么选一行,要么选一列,最少选多少个占满所有格子,把一个点变成一条边,左右连接1和-1的情况的点,二分图中最小点覆盖=最大匹配
dinic在二分图中跑最大流是m*sqrt(n)的,这里n条边,2*n个点
#include<bits/stdc++.h>
using namespace std;
const int N=8e6,inf=1e9;
int p[N],head[N],nex[N],e=1;
long long c[N],dp[N];
int pos[N],s,t;
void add(int a,int b,int x){
p[++e]=b;
nex[e]=head[a];
head[a]=e;
c[e]=x;
p[++e]=a;
nex[e]=head[b];
head[b]=e;
c[e]=0;
}
queue<int>q;
int bfs(){
int i,u,v;
for(i=0;i<=t;i++){
dp[i]=inf;
pos[i]=head[i];
}
dp[s]=0;
for(q.push(s);q.size();q.pop()){
u=q.front();
for(i=head[u];i;i=nex[i]){
v=p[i];
if(c[i]&&dp[v]>dp[u]+1){
dp[v]=dp[u]+1;
q.push(v);
}
}
}
return dp[t]!=inf;
}
long long dfs(int u,long long f){
if(u==t||f==0) return f;
long long v,k,sum=0;
for(int &i=pos[u];i;i=nex[i]){
v=p[i];
if(c[i]&&dp[v]==dp[u]+1){
k=dfs(v,min(c[i],f-sum));
sum+=k;
c[i]-=k;
c[i^1]+=k;
if(sum==f) break;
}
}
return sum;
}
long long maxflow(){
long long sum=0;
while(bfs()) sum+=dfs(s,inf);
return sum;
}
int ha1[N],h1,ha2[N],h2;
int id1(int x){
return lower_bound(ha1+1,ha1+h1+1,x)-ha1;
}
int id2(int x){
return lower_bound(ha2+1,ha2+h2+1,x)-ha2;
}
int T[N],X[N];
int main(){
int i,S,n,m,a,b;
scanf("%d",&S);
while(S--){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d",&T[i],&X[i]);
ha1[i]=X[i]+T[i];
ha2[i]=X[i]-T[i];
}
sort(ha1+1,ha1+1+n);
sort(ha2+1,ha2+1+n);
h1=unique(ha1+1,ha1+1+n)-ha1-1;
h2=unique(ha2+1,ha2+1+n)-ha2-1;
s=h1+h2+1;
t=s+1;
for(i=1;i<=t;i++) head[i]=0;
e=1;
for(i=1;i<=h1;i++) add(s,i,1);
for(i=1;i<=h2;i++) add(h1+i,t,1);
for(i=1;i<=n;i++){
a=id1(X[i]+T[i]);
b=id2(X[i]-T[i]);
add(a,b+h1,inf);
}
printf("%lld\n",maxflow());
}
return 0;
}