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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
| #include<bits\/stdc++.h>
using namespace std;
const int N=50100;
namespace MaxFlow{
const int M=2000000;
int head[N],cur[N],dep[N],cnt,S,T,s,t,ans,deg[N];
struct node{
int to,next,val;
}edge[M];
void ae(int u,int v,int w){
edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=0,head[v]=cnt++;
}
void AE(int u,int v,int l,int r){
\/\/ printf("%d %d [%d,%d]\n",u,v,l,r);
deg[v]+=l,deg[u]-=l;
edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=r-l,head[u]=cnt++;
edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=0,head[v]=cnt++;
}
queue<int>q;
inline bool bfs(){
memset(dep,0,sizeof(dep)),q.push(S),dep[S]=1;
while(!q.empty()){
register int x=q.front();q.pop();
for(register int i=cur[x]=head[x];i!=-1;i=edge[i].next)if(edge[i].val&&!dep[edge[i].to])dep[edge[i].to]=dep[x]+1,q.push(edge[i].to);
}
return dep[T]>0;
}
bool reach;
inline int dfs(int x,int flow){
if(x==T){
ans+=flow;
reach=true;
return flow;
}
int used=0;
for(register int &i=cur[x];i!=-1;i=edge[i].next){
if(!edge[i].val||dep[edge[i].to]!=dep[x]+1)continue;
register int ff=dfs(edge[i].to,min(edge[i].val,flow-used));
if(ff){
edge[i].val-=ff;
edge[i^1].val+=ff;
used+=ff;
if(used==flow)break;
}
}
return used;
}
inline void Dinic(){
while(bfs()){
reach=true;
while(reach)reach=false,dfs(S,0x3f3f3f3f);
}
}
}
using namespace MaxFlow;
int n,x[N],y[N],nw[N],ne[N],f[N],g[N],F[N],G[N],res;\/\/f:maximal when arriving at i g:maximal when leaving from i
vector<int>v[N],u[N],a;
void discrete(int *arr){
a.clear();
for(int i=0;i<=n;i++)a.push_back(arr[i]);
sort(a.begin(),a.end()),a.resize(unique(a.begin(),a.end())-a.begin());
for(int i=0;i<=n;i++)u[arr[i]=lower_bound(a.begin(),a.end(),arr[i])-a.begin()].push_back(i);
}
void buildgraph(){
for(int i=0;i<a.size();i++){
sort(u[i].begin(),u[i].end(),[](int X,int Y){return y[X]<y[Y];});
for(int j=1;j<u[i].size();j++)v[u[i][j-1]].push_back(u[i][j]);
u[i].clear();
}
}
bool cmp(int X,int Y){return x[X]<x[Y];}
stack<int>st;
bool lim[N<<1],vis[N<<1];\/\/if position i is able to reach maximum
vector<int>w[N<<1];
bool dfscheck(int x){
if(vis[x])return lim[x];vis[x]=true;
for(auto y:w[x])if(dfscheck(y)){
lim[x]=true;
if(x>n)AE(x-n-1,y,1,3*n);
}
return lim[x];
}
int main(){
scanf("%d",&n),memset(f,-1,sizeof(f)),memset(g,-1,sizeof(g)),memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]),nw[i]=x[i]+y[i],ne[i]=x[i]-y[i];
discrete(nw),buildgraph();
discrete(ne),buildgraph();
discrete(x),buildgraph();
\/\/ for(int i=0;i<=n;i++){for(auto j:v[i])printf("%d ",j);puts("");}
discrete(y),f[0]=0;
for(int i=0;i<a.size();i++){
sort(u[i].begin(),u[i].end(),cmp);
for(int j=0;j<u[i].size();j++)if(f[u[i][j]]!=-1)for(int k=0;k<u[i].size();k++){
int now=f[u[i][j]];
if(j<k)now+=k;
if(j>k)now+=u[i].size()-k-1;
if(g[u[i][k]]<=now)g[u[i][k]]=now,G[u[i][k]]=u[i][j];
}
for(auto j:u[i])if(g[j]!=-1)for(auto k:v[j])if(f[k]<=g[j]+1)f[k]=g[j]+1,F[k]=j;
}
for(int i=0;i<=n;i++)res=max(res,g[i]);
printf("%d\n",res);
for(int i=0;i<=n;i++){
if(g[i]!=res)continue;
while(i){
st.push(i);
int P=y[i];
int I=lower_bound(u[P].begin(),u[P].end(),i,cmp)-u[P].begin(),J=lower_bound(u[P].begin(),u[P].end(),G[i],cmp)-u[P].begin();
if(J<I){
for(int k=I-1;k>J;k--)st.push(u[P][k]);
for(int k=0;k<=J;k++)st.push(u[P][k]);
}
if(J>I){
for(int k=I+1;k<J;k++)st.push(u[P][k]);
for(int k=u[P].size()-1;k>=J;k--)st.push(u[P][k]);
}
i=F[G[i]];
}
break;
}
while(!st.empty())printf("%d ",st.top()),st.pop();puts("");
s=n+1,t=n+2,S=n+3,T=n+4;
for(int i=0;i<a.size();i++){
for(int j=0;j<u[i].size();j++)if(f[u[i][j]]!=-1)for(int k=0;k<u[i].size();k++){
int now=f[u[i][j]];
if(j<k)now+=k;
if(j>k)now+=u[i].size()-k-1;
if(g[u[i][k]]==now)w[u[i][j]].push_back(u[i][k]+n+1);
}
for(auto j:u[i])if(g[j]!=-1)for(auto k:v[j])if(f[k]==g[j]+1)w[j+n+1].push_back(k);
}
for(int i=0;i<=n;i++)if(g[i]==res)lim[i+n+1]=true;
dfscheck(0);
for(int i=0;i<=n;i++)ae(s,i,3*n),ae(i,t,3*n);
for(int i=0;i<=n;i++)if(deg[i]>0)ae(S,i,deg[i]);else ae(i,T,-deg[i]);
Dinic();
ae(t,s,3*n);
Dinic();
printf("%d\n",edge[cnt-1].val);
return 0;
}
|