1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
| #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<algorithm> using namespace std;
const int N=1e5+10,INF=1e9;
inline int Ri(){ register int r=0,c=getchar(); while(c<'0' || '9'<c) c=getchar(); while('0'<=c && c<='9') r=(r<<1)+(r<<3)+c-'0',c=getchar(); return r; }
int n,S,T; int x[N],y[N],dis[N<<1],head[N<<1]; vector<int> unix,uniy;
struct GRAPH{ int head[N<<1],nxt[N*6],to[N*6],cap[N*6],ncnt; void Init(int siz){ for(int i=0;i<=siz;i++) head[i]=0; ncnt=1; } void AddEdge(int u,int v,int ca){
int p=++ncnt,q=++ncnt; nxt[p]=head[u],to[p]=v,cap[p]=ca,head[u]=p; nxt[q]=head[v],to[q]=u,cap[q]=0 ,head[v]=q; } int operator [](const int &u){return head[u];} }Gr;
bool BFS(){ for(int i=1;i<=T;i++) dis[i]=-1,head[i]=Gr[i]; queue<int> que; que.push(S),dis[S]=0; while(!que.empty()){ int u=que.front();que.pop(); for(int it=head[u];it;it=Gr.nxt[it]){ int v=Gr.to[it]; if((~dis[v]) || Gr.cap[it]<=0) continue; dis[v]=dis[u]+1; if(v==T) return true; que.push(v); } } return false; } int Aug(int u,int in){
if(u==T) return in; int out=0; for(int &it=head[u];it;it=Gr.nxt[it]){ int v=Gr.to[it]; if(Gr.cap[it]<=0 || dis[v]!=dis[u]+1) continue; int tov=Aug(v,min(in-out,Gr.cap[it])); out+=tov; Gr.cap[it]-=tov,Gr.cap[it^1]+=tov; if(out==in) break; } return out; } int Dinic(){ int ret=0; while(BFS()) ret+=Aug(S,INF); return ret; }
int main(){ for(int cas=Ri();cas;cas--){ n=Ri(); unix.clear(),uniy.clear(); for(int i=1;i<=n;i++){ int a=Ri(),b=Ri(); x[i]=a+b,y[i]=a-b; unix.push_back(x[i]); uniy.push_back(y[i]); } sort(unix.begin(),unix.end()),unix.erase(unique(unix.begin(),unix.end()),unix.end());; sort(uniy.begin(),uniy.end()),uniy.erase(unique(uniy.begin(),uniy.end()),uniy.end());; int p=unix.size(),q=uniy.size(); S=p+q+1,T=S+1; Gr.Init(T); for(int i=1;i<=p;i++) Gr.AddEdge(S,i,1); for(int i=p+1;i<S;i++) Gr.AddEdge(i,T,1); for(int i=1;i<=n;i++){ x[i]=lower_bound(unix.begin(),unix.end(),x[i])-unix.begin()+1, y[i]=lower_bound(uniy.begin(),uniy.end(),y[i])-uniy.begin()+1; Gr.AddEdge(x[i],y[i]+p,1); } printf("%d\n",Dinic()); } return 0; }
|