6、建图最小流
这题细节太多了!!!
建图的方法我是学PoPoQQQ大爷的,先正着dp一遍,再倒着dp一遍。
我的数组初始化错了,所以一直在WA,最后千辛万苦调到只有第7个点会T了。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #include<map> #define maxn 50010 #define maxm 2000100 #define inf 1000000000 using namespace std; struct yts { int x,y,id; }a[maxn]; struct yts1 { int x,y,z; }e[maxm]; map<int,int> m1,m2,m3;//和、差、横坐标 int head[maxn],to[maxm],c[maxm],next[maxm],q[maxn],d[maxn]; int dp[maxn],g[maxn],mx[maxn],fr[maxn],st[maxn],seq[maxn],in[maxn],cnt[maxn],f[maxn]; bool tag[maxn],flag[maxn]; int n,m,s,t,num,ans,pos,tot,S,T,Ans; bool cmp(yts x,yts y) { return x.y<y.y || (x.y==y.y && x.x<y.x); } int findl(int x) { int l=1,r=n,ans; while (l<=r) { int mid=(l+r)/2; if (a[mid].y>=x) ans=mid,r=mid-1; else l=mid+1; } return ans; } int findr(int x) { int l=1,r=n,ans; while (l<=r) { int mid=(l+r)/2; if (a[mid].y<=x) ans=mid,l=mid+1; else r=mid-1; } return ans; } void print(int x,int y) { int l=findl(a[x].y),r=findr(a[x].y); if (x<y) { for (int i=x;i>=l;i--) seq[++tot]=i; for (int i=x+1;i<=y;i++) seq[++tot]=i; } else { for (int i=x;i<=r;i++) seq[++tot]=i; for (int i=x-1;i>=y;i--) seq[++tot]=i; } } void solve() { int top=0;tot=0; while (pos) { if (tag[pos]) { st[++top]=pos;st[++top]=fr[pos]; pos=g[fr[pos]]; } else st[++top]=pos,pos=g[pos]; } while (top) { if (top>1 && a[st[top]].y==a[st[top-1]].y) { print(st[top],st[top-1]); top-=2; continue; } seq[++tot]=st[top--]; } for (int i=1;i<tot;i++) printf("%d ",a[seq[i]].id);printf("%d\n",a[seq[tot]].id); } void DP() { for (int i=1;i<=n;i++) dp[i]=mx[i]=-inf; dp[0]=0; for (int i=0,t=0;i<=n;i=++t) { while (t<n && a[t+1].y==a[t].y) t++; for (int j=i;j<=t;j++) { if (m1.find(a[j].x+a[j].y)!=m1.end()) { int p=m1[a[j].x+a[j].y]; if (dp[p]+1>dp[j]) dp[j]=dp[p]+1,g[j]=p; } m1[a[j].x+a[j].y]=j; if (m2.find(a[j].x-a[j].y)!=m2.end()) { int p=m2[a[j].x-a[j].y]; if (dp[p]+1>dp[j]) dp[j]=dp[p]+1,g[j]=p; } m2[a[j].x-a[j].y]=j; if (m3.find(a[j].x)!=m3.end()) { int p=m3[a[j].x]; if (dp[p]+1>dp[j]) dp[j]=dp[p]+1,g[j]=p; } m3[a[j].x]=j; } int pos=-1; for (int j=i+1;j<=t;j++) { if (pos==-1 || dp[j-1]>dp[pos]) pos=j-1; if (dp[pos]+j-i>mx[j]) mx[j]=dp[pos]+j-i,fr[j]=pos; } pos=-1; for (int j=t-1;j>=i;j--) { if (pos==-1 || dp[j+1]>dp[pos]) pos=j+1; if (dp[pos]+t-j>mx[j]) mx[j]=dp[pos]+t-j,fr[j]=pos; } for (int j=i;j<=t;j++) if (mx[j]>dp[j]) dp[j]=mx[j],tag[j]=1; } pos=0; for (int i=1;i<=n;i++) if (dp[i]>dp[pos]) pos=i; Ans=dp[pos]; printf("%d\n",dp[pos]); } void DP2() { for (int i=1;i<=n;i++) if (dp[i]==Ans) f[i]=1; else f[i]=0; for (int i=1;i<=n;i++) mx[i]=-inf; m1.clear();m2.clear();m3.clear(); for (int i=n,t=n;i>=0;i=--t) { while (t && a[t-1].y==a[t].y) t--; for (int j=t;j<=i;j++) { if (m1.find(a[j].x+a[j].y)!=m1.end()) { int p=m1[a[j].x+a[j].y]; if (f[p]+1>f[j]) f[j]=f[p]+1; } m1[a[j].x+a[j].y]=j; if (m2.find(a[j].x-a[j].y)!=m2.end()) { int p=m2[a[j].x-a[j].y]; if (f[p]+1>f[j]) f[j]=f[p]+1; } m2[a[j].x-a[j].y]=j; if (m3.find(a[j].x)!=m3.end()) { int p=m3[a[j].x]; if (f[p]+1>f[j]) f[j]=f[p]+1; } m3[a[j].x]=j; } int pos=-1; for (int j=t+1;j<=i;j++) { if (pos==-1 || f[j-1]+i-j+1>f[pos]+i-pos) pos=j-1; if (f[pos]+i-pos>mx[j]) mx[j]=f[pos]+i-pos; } pos=-1; for (int j=i-1;j>=t;j--) { if (pos==-1 || f[j+1]+j+1-t>f[pos]+pos-t) pos=j+1; if (f[pos]+pos-t>mx[j]) mx[j]=f[pos]+pos-t; } for (int j=t;j<=i;j++) if (mx[j]>f[j]) f[j]=mx[j]; } } void addedge(int x,int y,int z) { num++;to[num]=y;c[num]=z;next[num]=head[x];head[x]=num; num++;to[num]=x;c[num]=0;next[num]=head[y];head[y]=num; } bool bfs() { memset(d,-1,sizeof(d)); int l=0,r=1; q[1]=S;d[S]=0; while (l<r) { int x=q[++l]; for (int p=head[x];p;p=next[p]) if (c[p] && d[to[p]]==-1) { d[to[p]]=d[x]+1; q[++r]=to[p]; } } if (d[T]==-1) return 0; else return 1; } int find(int x,int low) { if (x==T || low==0) return low; int totflow=0; for (int p=head[x];p;p=next[p]) if (c[p] && d[to[p]]==d[x]+1) { int a=find(to[p],min(c[p],low)); c[p]-=a;c[p^1]+=a; low-=a;totflow+=a; if (low==0) return totflow; } if (low) d[x]=-1; return totflow; } void Dinic() { int ans=0; while (bfs()) ans+=find(S,inf); } void sol() { num=1; memset(head,0,sizeof(head)); for (int i=1;i<=m;i++) addedge(e[i].x,e[i].y,e[i].z); Dinic(); addedge(t,s,inf); Dinic(); printf("%d\n",c[num]); } void Addedge(int x,int y,int z) { e[++m].x=x;e[m].y=y;e[m].z=z; } void build() { s=n+1;t=n+2;S=n+3;T=n+4; m1.clear();m2.clear();m3.clear(); for (int i=n;i>=0;i--) { if (m1.find(a[i].x+a[i].y)!=m1.end()) { int p=m1[a[i].x+a[i].y]; if (dp[i]+f[p]==Ans) Addedge(i,p,inf),in[i]--,in[p]++; } if (m2.find(a[i].x-a[i].y)!=m2.end()) { int p=m2[a[i].x-a[i].y]; if (dp[i]+f[p]==Ans) Addedge(i,p,inf),in[i]--,in[p]++; } if (m3.find(a[i].x)!=m3.end()) { int p=m3[a[i].x]; if (dp[i]+f[p]==Ans) Addedge(i,p,inf),in[i]--,in[p]++; } m1[a[i].x+a[i].y]=i; m2[a[i].x-a[i].y]=i; m3[a[i].x]=i; } for (int i=0;i<=n;i++) Addedge(s,i,inf),Addedge(i,t,inf); for (int i=0;i<=n;i++) if (in[i]>0) cnt[i]=2*(m+1)+2,Addedge(S,i,in[i]); else if (in[i]<0) cnt[i]=2*(m+1)+2,Addedge(i,T,-in[i]); } int main() { //freopen("farm16.in","r",stdin); //freopen("farm16.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d%d",&a[i].x,&a[i].y); a[i].id=i; } sort(a+1,a+n+1,cmp); DP(); DP2(); solve(); build(); sol(); return 0; }