dp+有源汇上下界的最小流;
dp:按pair
#include
#define rep(i,k,n) for(int i=k;i<=(n);i++)
#define rep2(i,k,n) for(int i=k;i>=(n);i--)
using namespace std;
const int N=50305;
const int M=600005;
const int inf=0x3f3f3f3f;
struct node{
int x,y,id;node(int x=0,int y=0,int id=0):x(x),y(y),id(id){}
}a[N];
bool cmp(node A,node B){
return A.y==B.y ? A.xint n;
map<int,int> mp1,mp2,mp3;
int f[N],fa[N],from[N],mx[N],pos,tag[N],stk[N],top,f2[N],ans,in[N],out[N];
int S,T,SS,TT,cur[N],Sum=0;
void dp1(){
memset(f,-0x7f,sizeof(f));
memset(mx,-0x7f,sizeof(f));
f[0]=0;
int t=0;
for(int i=0;i<=n;i=++t){
while(t1].y==a[t].y)t++;
rep(j,i,t){
if(mp1.find(a[j].x+a[j].y)!=mp1.end()){
int p=mp1[a[j].x+a[j].y];
if(f[p]+1>f[j])f[j]=f[p]+1,fa[j]=p;
}
mp1[a[j].x+a[j].y]=j;
if(mp2.find(a[j].x-a[j].y)!=mp2.end()){
int p=mp2[a[j].x-a[j].y];
if(f[p]+1>f[j])f[j]=f[p]+1,fa[j]=p;
}
mp2[a[j].x-a[j].y]=j;
if(mp3.find(a[j].x)!=mp3.end()){
int p=mp3[a[j].x];
if(f[p]+1>f[j])f[j]=f[p]+1,fa[j]=p;
}
mp3[a[j].x]=j;
}
int now=-1;
rep(j,i+1,t){
if(now==-1||f[j-1]>f[now])now=j-1;
if(f[now]+j-i>mx[j])mx[j]=f[now]+j-i,from[j]=now;
}
now=-1;
rep2(j,t-1,i){
if(now==-1||f[j+1]>f[now])now=j+1;
if(f[now]+t-j>mx[j])mx[j]=f[now]+t-j,from[j]=now;
}
rep(j,i,t)if(mx[j]>f[j])f[j]=mx[j],tag[j]=1;
}
pos=0;
rep(i,1,n)if(!pos||f[i]>f[pos])pos=i;
}
void dp2(){
mp1.clear(),mp2.clear(),mp3.clear();
memset(f2,-0x7f,sizeof(f2));
memset(mx,-0x7f,sizeof(f));
rep(i,1,n)if(f[i]==ans)f2[i]=1;
int t=n;
for(int i=n;i>=0;i=--t){
while(t && a[t-1].y==a[t].y)t--;
rep2(j,i,t){
if(mp1.find(a[j].x+a[j].y)!=mp1.end()){
int p=mp1[a[j].x+a[j].y];
if(f2[p]+1>f2[j])f2[j]=f2[p]+1;
}
mp1[a[j].x+a[j].y]=j;
if(mp2.find(a[j].x-a[j].y)!=mp2.end()){
int p=mp2[a[j].x-a[j].y];
if(f2[p]+1>f2[j])f2[j]=f2[p]+1;
}
mp2[a[j].x-a[j].y]=j;
if(mp3.find(a[j].x)!=mp3.end()){
int p=mp3[a[j].x];
if(f2[p]+1>f2[j])f2[j]=f2[p]+1;
}
mp3[a[j].x]=j;
}
int now=-1;
rep(j,t+1,i){
if(now==-1||f2[j-1]+i-j+1>f2[now]+i-now)now=j-1;
if(f2[now]+i-now>mx[j])mx[j]=f2[now]+i-now;
}
now=-1;
rep2(j,i-1,t){
if(now==-1||f2[j+1]+j+1-t>f2[now]+now-t)now=j+1;
if(f2[now]+now-t>mx[j])mx[j]=f2[now]+now-t;
}
rep(j,t,i)if(mx[j]>f2[j])f2[j]=mx[j];
}
}
void print(int x,int y){
if(xint lx=x;
while(lx>=0 && a[lx].y==a[y].y)printf("%d ",a[lx].id),lx--;
int rx=x+1;
while(rx<=y && a[rx].y==a[y].y)printf("%d ",a[rx].id),rx++;
}else{
int rx=x;
while(rx<=n && a[rx].y==a[y].y)printf("%d ",a[rx].id),rx++;
int lx=x-1;
while(lx>=y && a[lx].y==a[y].y)printf("%d ",a[lx].id),lx--;
}
}
void solve(){
printf("%d\n",ans=f[pos]);
top=0;
int now=pos;
while(now!=-1){
if(now)stk[++top]=now;
if(tag[now]){
stk[++top]=from[now];
now=fa[from[now]];
}else now=fa[now];
}
while(top){
if(a[stk[top]].y==a[stk[top-1]].y)print(stk[top],stk[top-1]),top--;
else printf("%d ",a[stk[top]].id);
top--;
}
printf("\n");
}
struct E{
int to,next,cap;E(int to=0,int next=0,int cap=0):to(to),next(next),cap(cap){}
}edge[M];
int head[N],tot=1;
void add(int x,int y,int cap){
edge[++tot]=E(y,head[x],cap);head[x]=tot;
edge[++tot]=E(x,head[y],0);head[y]=tot;
}
void build(){
mp1.clear(),mp2.clear(),mp3.clear();
S=n+1,T=S+1,SS=T+1,TT=SS+1;
rep(i,0,n){
if(mp1.find(a[i].x+a[i].y)!=mp1.end()){
int p=mp1[a[i].x+a[i].y];
if(f[p]+f2[i]==ans){
add(p,i,inf);
out[p]++;
in[i]++;
}
}
mp1[a[i].x+a[i].y]=i;
if(mp2.find(a[i].x-a[i].y)!=mp2.end()){
int p=mp2[a[i].x-a[i].y];
if(f[p]+f2[i]==ans){
add(p,i,inf);
out[p]++;
in[i]++;
}
}
mp2[a[i].x-a[i].y]=i;
if(mp3.find(a[i].x)!=mp3.end()){
int p=mp3[a[i].x];
if(f[p]+f2[i]==ans){
add(p,i,inf);
out[p]++;
in[i]++;
}
}
mp3[a[i].x]=i;
}
rep(i,0,n){
add(S,i,inf),add(i,T,inf);
if(in[i]>out[i]){
add(SS,i,in[i]-out[i]);
Sum+=in[i]-out[i];
}else{
add(i,TT,out[i]-in[i]);
Sum+=out[i]-in[i];
}
}
}
queue<int> Q;
int d[N];
bool bfs(){
memset(d,0x7f,sizeof(d));
memcpy(cur,head,sizeof(head));
Q.push(SS);d[SS]=0;
while(!Q.empty()){
int u=Q.front();Q.pop();
for(int i=head[u];i;i=edge[i].next)if(edge[i].cap){
int v=edge[i].to;
if(d[v]>d[u]+1){
d[v]=d[u]+1;Q.push(v);}
}
}return d[TT]int dfs(int u,int a){
if(u==TT || !a)return a;
int flow=0,f;
for(int &i=cur[u];i;i=edge[i].next)if(edge[i].cap){
int v=edge[i].to;
if(d[v]==d[u]+1 && (f=dfs(v,min(a,edge[i].cap)))>0){
edge[i].cap-=f;
edge[i^1].cap+=f;
flow+=f;
a-=f;
if(!a)return flow;
}
}
return flow;
}
void dinic(){
while(bfs()){
dfs(SS,inf);
}
}
int main(){
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%d",&n);
int x,y;
rep(i,1,n){
scanf("%d%d",&x,&y);
a[i]=node(x,y,i);
}sort(a+1,a+n+1,cmp);
memset(fa,-1,sizeof(fa));
if(n==1){printf("0\n\n0\n");return 0;}
dp1();
solve();
dp2();
build();
dinic();
add(T,S,inf);
dinic();
printf("%d\n",edge[tot].cap);
}