记录编号 401529 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOI 2015]小园丁与老司机 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 0.730 s
提交时间 2017-05-02 21:50:10 内存使用 101.40 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e6+10;
int n,x[N],y[N];
vector<int> go[N],bk[N];
void add(int f,int t){
	go[f].push_back(t);
	bk[t].push_back(f);
}
bool cmp2(int a,int b){//right
	return y[a]==y[b]?x[a]<x[b]:y[a]<y[b];
}
bool cmp3(int a,int b){//up
	return x[a]==x[b]?y[a]<y[b]:x[a]<x[b];
}
bool cmp4(int a,int b){//left45
	return x[a]+y[a]==x[b]+y[b]?y[a]<y[b]:x[a]+y[a]<x[b]+y[b];
}
bool cmp5(int a,int b){//right45
	return x[a]-y[a]==x[b]-y[b]?y[a]<y[b]:x[a]-y[a]<x[b]-y[b];
}
struct edge{int f,t,g;}w[N];
int head[N],next[N],cnt=1;
void add(int f,int t,int g){
	w[++cnt]=(edge){f,t,g};
	next[cnt]=head[f];
	head[f]=cnt;
	w[++cnt]=(edge){t,f,0};
	next[cnt]=head[t];
	head[t]=cnt;
}
struct st{
	int x,i,df;
	st(int X=0,int DF=0){x=X;i=head[x];df=DF;}
}z[N];
int l[N],top,s,t,S,T,ans;
#define V z[top].x
#define E z[top].i
#define F z[top].df
void change(){
	int df=F;ans-=df;
	for (int i=top-1;i;i--){
		w[z[i].i].g-=df;
		w[z[i].i^1].g+=df;
		z[i].df-=df;
		if (!z[i].df) top=i;
	}
}
queue<int> Q;
void bfs(){
	for (int i=0;i<=T;i++) l[i]=0;
	l[S]=1;Q.push(S);
	while (!Q.empty()){
		int v=Q.front();Q.pop();
		if (l[T]) continue;
		for (int i=head[v];i;i=next[i])
		if (w[i].g&&!l[w[i].t])
			l[w[i].t]=l[v]+1,Q.push(w[i].t);
	}
}
bool dinic(){
	bfs();
	if (!l[T]) return 0;
	z[top=1]=st(S,1e9);
	while (top){
		if (V==T) change(),E=next[E];else
		if (!E) l[V]=0,top--,E=next[E];else
		if (w[E].g&&l[w[E].t]==l[V]+1)
			z[top+1]=st(w[E].t,min(F,w[E].g)),top++;
		else E=next[E];
	}
	return 1;
}
int dp[N],f[N],q[N],from_dp[N],from_f[N];
//dp[i]表示走到i,之后向上走最多经过的点数
//f[i]表示走到i,尚未左右移动时最多经过的点数(不含自己)
int que[N],size,rank[N],pre[N],suc[N];
void update(int *dp,int *from,int x,int p,int v){
	if (v>dp[x]) dp[x]=v,from[x]=p;
}
void work(){
	for (int i=1;i<=size;i++){
		rank[que[i]]=i;
		if (i>1) pre[que[i]]=que[i-1];
		if (i<size) suc[que[i]]=que[i+1];
	}
	for (int i=1,Max=-1e9,p=0;i<=size;i++){
		update(dp,from_dp,que[i],que[i],f[que[i]]+1);
		update(dp,from_dp,que[i],p,Max+i);
		if (f[que[i]]>Max) Max=f[p=que[i]];
	}
	for (int i=size,Max=-1e9,p=0;i;i--){
		update(dp,from_dp,que[i],p,Max+size-i+1);
		if (f[que[i]]>Max) Max=f[p=que[i]];
	}
	for (int i=1;i<=size;i++){
		int v=que[i];
		for (int i=go[v].size()-1;i>=0;i--)
			update(f,from_f,go[v][i],v,dp[v]);
	}
}
void solution(int p){//输出到达dp[p]的方案
	if (!p) return;
	int f=from_dp[p];
	solution(from_f[f]);
	printf("%d ",f);
	if (f==p) return;
	if (rank[f]<rank[p]){
		for (int i=pre[f];i;i=pre[i]) printf("%d ",i);
		for (int i=suc[f];i!=p;i=suc[i]) printf("%d ",i);
	}
	else{
		for (int i=suc[f];i;i=suc[i]) printf("%d ",i);
		for (int i=pre[f];i!=p;i=pre[i]) printf("%d ",i);
	}
	printf("%d ",p);
}
bool ok_dp[N],ok_f[N];
void add_edge(){
	for (int i=1,Min=1e9;i<=size;i++){
		if (ok_dp[que[i]]&&f[que[i]]+1==dp[que[i]]) ok_f[que[i]]=1;
		if (f[que[i]]==Min) ok_f[que[i]]=1;
		if (ok_dp[que[i]]) Min=min(Min,dp[que[i]]-size+i-1);
	}
	for (int i=size,Min=1e9;i>=0;i--){
		if (f[que[i]]==Min) ok_f[que[i]]=1;
		if (ok_dp[que[i]]) Min=min(Min,dp[que[i]]-i);
	}
	for (int i=1;i<=size;i++){
		int v=que[i];
		if (ok_f[v]){
			for (int i=bk[v].size()-1;i>=0;i--)
			if (dp[bk[v][i]]==f[v]){
				int u=bk[v][i];
				ok_dp[u]=1;
				add(u,v,1e9);
				ans++;
				add(t,v,1);
				add(u,s,1);
			}
		}
	}
}
void makegraph(){
	t=n+1;s=t+1;
	for (int i=0;i<=n;i++) add(s,i,1e9),add(i,t,1e9);
	for (int i=n;i>=0;){
		int flag=y[q[i]];
		size=0;
		while (i>=0&&y[q[i]]==flag) que[++size]=q[i--];
		add_edge();
	}
}
int main()
{
	freopen("farm.in","r",stdin);
	freopen("farm.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
	for (int i=0;i<=n;i++) q[i]=i;
	sort(q,q+n+1,cmp3);
	for (int i=0;i<n;i++)
		if (x[q[i]]==x[q[i+1]]) add(q[i],q[i+1]);
	sort(q,q+n+1,cmp4);
	for (int i=0;i<n;i++)
		if (x[q[i]]+y[q[i]]==x[q[i+1]]+y[q[i+1]]) add(q[i],q[i+1]);
	sort(q,q+n+1,cmp5);
	for (int i=0;i<n;i++)
		if (x[q[i]]-y[q[i]]==x[q[i+1]]-y[q[i+1]]) add(q[i],q[i+1]);
	sort(q,q+n+1,cmp2);
	for (int i=1;i<=n;i++) f[i]=dp[i]=-1e9;
	for (int i=0;i<=n;){
		int flag=y[q[i]];
		size=0;
		while (y[q[i]]==flag) que[++size]=q[i++];
		work();
	}
	int ans1=-1e9,p=0;
	for (int i=0;i<=n;i++)
		if (dp[i]>ans1) ans1=dp[p=i];
	printf("%d\n",ans1-1);
	for (int i=0;i<=n;i++)
		if (dp[i]==ans1) ok_dp[i]=1;
	solution(p);puts("");
	makegraph();
	S=t;T=s;
	while (dinic());
	printf("%d\n",ans);
	return 0;
}