#include<bits/stdc++.h>
using namespace std;
const int N=200010,M=200010;
struct node{
int x,y,id;
}p[N];
struct edge{
int y,nex,c;
}s[M<<1];
int first[N],head[N],len=1,qs[N],st,ed,d[N];
int nex[N][3],f[N],ans[N],from[N],op[N],s1,t1,s2,t2,lef[N],rig[N],pos[N];//上,左上,右上
vector<int> V[N],P[N],S;
int sta[N],top=0,mmax=-1e9;
bool tf[N][2];
int n;
bool cmp1(const node&a,const node&b){return a.y!=b.y?a.y<b.y:a.x<b.x;}
bool cmp2(const node&a,const node&b){return a.x!=b.x?a.x<b.x:a.y<b.y;}
bool cmp3(const node&a,const node&b){return a.x+a.y!=b.x+b.y?a.x+a.y<b.x+b.y:a.x<b.x;}
bool cmp4(const node&a,const node&b){return a.y-a.x!=b.y-b.x?a.y-a.x<b.y-b.x:a.x<b.x;}
bool cmp5(const node&a,const node&b){return a.id<b.id;}
void ins(int x,int y,int a,int b){
op[x]-=a;op[y]+=a;
s[++len]=(edge){y,first[x],b-a};first[x]=len;
s[++len]=(edge){x,first[y],0};first[y]=len;
}
void gins(int x,int type){
if(tf[x][type]) return ;
if(type==0){
tf[x][0]=true;
for(auto i:P[x]) ins(i,x,1,1e9),gins(i,1);
}
if(type==1){
tf[x][1]=true;
if(top!=mmax){
sta[++top]=x;
for(auto i:V[x]) if(i!=x){
if(pos[i]<pos[x]){
int now=lef[x];
while(now!=i) sta[++top]=now,now=lef[now];
while(lef[now]) now=lef[now];
while(now!=i) sta[++top]=now,now=rig[now];
sta[++top]=i;
}
else{
int now=rig[x];
while(now!=i) sta[++top]=now,now=rig[now];
while(rig[now]) now=rig[now];
while(now!=i) sta[++top]=now,now=lef[now];
sta[++top]=i;
}
break;
}
else break;
}
for(auto i:V[x]) gins(i,0);
}
}
bool bfs(int S,int T){
for(int i=1;i<=T;i++) d[i]=0,first[i]=head[i];
d[qs[st=ed=1]=S]=1;
while(st<=ed){
int x=qs[st++];
for(int i=first[x];i;i=s[i].nex) if(s[i].c && !d[s[i].y]){
d[s[i].y]=d[x]+1;
qs[++ed]=s[i].y;
}
}
return d[T]!=0;
}
int dfs(int x,int T,int t){
if(x==T) return t;
int tot=0;
for(int&i=first[x];i;i=s[i].nex) if(s[i].c && d[s[i].y]==d[x]+1){
int now=dfs(s[i].y,T,min(t-tot,s[i].c));
s[i].c-=now;s[i^1].c+=now;tot+=now;
if(tot==t) break;
}
return tot;
}
int Dinic(int S,int T){
int tot=0,dx;
while(bfs(S,T)){
dx=dfs(S,T,1e9);
while(dx) tot+=dx,dx=dfs(S,T,1e9);
}
return tot;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d %d",&p[i].x,&p[i].y),p[i].id=i;
n++;p[n]=(node){0,0,n};
for(int i=1;i<=n;i++) ans[i]=-1e9;ans[n]=0;
s1=n+1;t1=s1+1;s2=t1+1;t2=s2+1;
sort(p+1,p+1+n,cmp2);
for(int i=1;i<n;i++) if(p[i].x==p[i+1].x)
nex[p[i].id][0]=p[i+1].id;
sort(p+1,p+1+n,cmp3);
for(int i=1;i<n;i++) if(p[i].x+p[i].y==p[i+1].x+p[i+1].y)
nex[p[i+1].id][1]=p[i].id;
sort(p+1,p+1+n,cmp4);
for(int i=1;i<n;i++) if(p[i].y-p[i].x==p[i+1].y-p[i+1].x)
nex[p[i].id][2]=p[i+1].id;
sort(p+1,p+1+n,cmp1);
int now=1;
while(now<=n){
int L=now,R=now,mmax=-1e9;S.resize(0);
while(p[R+1].y==p[R].y) R++;
for(int i=L;i<=R;i++){
f[p[i].id]=ans[p[i].id],V[p[i].id].push_back(p[i].id);
if(i!=L) lef[p[i].id]=p[i-1].id;
if(i!=R) rig[p[i].id]=p[i+1].id;
pos[p[i].id]=i;
}
for(int i=L;i<=R;i++){
if(mmax+i-L>ans[p[i].id]) ans[p[i].id]=mmax+i-L,V[p[i].id]=S;
else if(mmax+i-L==ans[p[i].id]) for(auto j:S) V[p[i].id].push_back(j);
if(f[p[i].id]>mmax) mmax=f[p[i].id],S.resize(0);
if(f[p[i].id]==mmax) S.push_back(p[i].id);
}
mmax=-1e9;S.resize(0);
for(int i=R;i>=L;i--){
if(mmax+R-i>ans[p[i].id]) ans[p[i].id]=mmax+R-i,V[p[i].id]=S;
else if(mmax+R-i==ans[p[i].id]) for(auto j:S) V[p[i].id].push_back(j);
if(f[p[i].id]>mmax) mmax=f[p[i].id],S.resize(0);
if(f[p[i].id]==mmax) S.push_back(p[i].id);
}
for(int i=L;i<=R;i++){
for(int j=0;j<3;j++) if(nex[p[i].id][j]){
if(ans[nex[p[i].id][j]]<ans[p[i].id]+1)
P[nex[p[i].id][j]].resize(0),ans[nex[p[i].id][j]]=ans[p[i].id]+1;
if(ans[nex[p[i].id][j]]==ans[p[i].id]+1)
P[nex[p[i].id][j]].push_back(p[i].id);
}
}
now=R+1;
}
sort(p+1,p+1+n,cmp5);
for(int i=1;i<=n;i++) mmax=max(mmax,ans[i]);
printf("%d\n",mmax);
for(int i=1;i<=n;i++) if(ans[i]==mmax) gins(i,1);
for(int i=mmax;i>=1;i--) printf("%d ",sta[i]);printf("\n");
for(int i=1;i<=n;i++) ins(s1,i,0,1e9),ins(i,t1,0,1e9);
for(int i=1;i<=t1;i++)
if(op[i]>0) ins(s2,i,0,op[i]);
else if(op[i]<0) ins(i,t2,0,-op[i]);
ins(t1,s1,0,1e9);
for(int i=1;i<=t2;i++) head[i]=first[i];
Dinic(s2,t2);
int tot=s[len].c;s[len].c=s[len^1].c=0;
printf("%d\n",tot-Dinic(t1,s1));
}
题目描述
小园丁 Mr. S 负责看管一片田野,田野可以看作一个二维平面。田野上有 𝑛n 棵 许愿树,编号 1,2,3,…,𝑛1,2,3,…,n ,每棵树可以看作平面上的一个点,其中第 𝑖i 棵树 (1≤𝑖≤𝑛)(1≤i≤n) 位于坐标 (𝑥𝑖,𝑦𝑖)(xi,yi) 。任意两棵树的坐标均不相同。
老司机 Mr. P 从原点 (0,0)(0,0) 驾车出发,进行若干轮行动。每一轮,Mr. P 首先选择任意一个满足以下条件的方向:
1.为左、右、上、左上 45°45°、右上 45°45° 五个方向之一。
2.沿此方向前进可以到达一棵他尚未许愿过的树。
完成选择后,Mr.P 沿该方向直线前进,必须到达该方向上距离最近的尚未许愿的树,在树下许愿并继续下一轮行动。如果没有满足条件的方向可供选择,则停止行动。他会采取最优策略,在尽可能多的树下许愿。若最优策略不唯一,可以选择任意一种。
不幸的是,小园丁 Mr.S 发现由于田野土质松软,老司机 Mr.P 的小汽车在每轮行进过程中,都会在田野上留下一条车辙印,一条车辙印可看作以两棵树(或原点和一棵树)为端点的一条线段。
在 Mr.P 之后,还有很多许愿者计划驾车来田野许愿,这些许愿者都会像 Mr.P 一样任选一种最优策略行动。Mr.S 认为非左右方向(即上、左上 45°45°、右 上 45°45° 三个方向)的车辙印很不美观,为了维护田野的形象,他打算租用一些轧路机,在这群许愿者到来之前夯实所有“可能留下非左右方向车辙印”的地面。“可能留下非左右方向车辙印”的地面应当是田野上的若干条线段,其中每条线段都包含在某一种最优策略的行进路线中。每台轧路机都采取满足以下三个条件的工作模式:
1.从原点或任意一棵树出发。
2.只能向上、左上 45°45°、右上 45°45° 三个方向之一移动,并且只能在树下改变方向或停止。
3.只能经过“可能留下非左右方向车辙印”的地面,但是同一块地面可以 被多台轧路机经过。
现在 Mr. P 和 Mr. S 分别向你提出了一个问题:
1.请给 Mr.P 指出任意一条最优路线。
2.请告诉 Mr.S 最少需要租用多少台轧路机。
输入格式
第 11 行包含 11 个正整数 𝑛n,表示许愿树的数量。
接下来 𝑛n 行,第 𝑖+1i+1 行包含 22 个整数 𝑥𝑖,𝑦𝑖xi,yi,中间用单个空格隔开,表示第 𝑖i 棵许愿树的坐标。
输出格式
包括 33 行。
第 11 行输出 11 个整数 𝑚m,表示 Mr. P 最多能在多少棵树下许愿。
输出文件的第 22 行输出 𝑚m 个整数,相邻整数之间用单个空格隔开,表示 Mr.P 应该依次在哪些树下许愿。
输出文件的第 33 行输出 11 个整数,表示 Mr. S 最少需要租用多少台轧路机。
输入输出样例
输入 #1
6 -1 1 1 1 -2 2 0 8 0 9 0 10
输出 #1
3 2 1 3 3
输入 #2
4 0 1 -2 1 2 1 3 2
输出 #2
4 1 2 3 4 2
说明/提示
样例 1 解释
最优路线共 22 条,可许愿 33 次:(0,0)→(1,1)→(−1,1)→(−2,2)(0,0)→(1,1)→(−1,1)→(−2,2) 或 (0,0)→(0,8)→(0,9)→(0,10)(0,0)→(0,8)→(0,9)→(0,10)。
至少 33 台轧路机,路线是 (0,0)→(1,1)(0,0)→(1,1),(−1,1)→(−2,2)(−1,1)→(−2,2) 和 (0,0)→(0,8)→(0,9)→(0,10)(0,0)→(0,8)→(0,9)→(0,10)。
样例 2 解释
最优路线唯一:(0,0)→(0,1)→(−2,1)→(2,1)→(3,2)(0,0)→(0,1)→(−2,1)→(2,1)→(3,2),可许愿 44 次。其中在 (0,1)(0,1) 许愿后,从 (−2,1)(−2,1) 出发沿着向右的方向能够到达的最近的未许愿过的树是 (2,1)(2,1),所以可以到达 (2,1)(2,1)。
而如果沿着 (0,0)→(0,1)→(2,1)→(−2,1)(0,0)→(0,1)→(2,1)→(−2,1) 的方向前进,此时 (−2,1)(−2,1) 右边所有树都是许愿过的,根据题目条件规定,停止前进。故无法获得最优解。
(0,0)→(0,1)(0,0)→(0,1) 与 (2,1)→(3,2)(2,1)→(3,2) 会留下非左右方向车辙印,需 22 台轧路机。