http://poj.org/problem?id=2749
2-sat + 二分
在二分里面根据情况 有时候是求大的 有时候是求小的
这个二分里面 我分的时候
while(l<r)
l=mid+1;
r=mid;
因为 mid可能就是答案 还有就是如果最后停在 r为有边界时 r可能不是答案需要特判 一下
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<vector> #include<set> #include<queue> #include<stack> #include<cmath> #define LL long long using namespace std; const int N=1005; int head[N],I; struct ss { int j,next; }side[N*N]; struct key { int i,j; }hate[N],fri[N]; int Adist[N],Bdist[N]; int low[N],dfn[N],f[N],deep; bool in[N],visited[N]; stack<int>st; int ans[N*N]; int n,m1,m2; void build(int x,int y) { side[I].j=y; side[I].next=head[x]; head[x]=I++; } void Tarjan(int x) { visited[x]=true; in[x]=true; st.push(x); low[x]=dfn[x]=deep++; for(int t=head[x];t!=-1;t=side[t].next) { int k=side[t].j; if(visited[k]==false) { Tarjan(k); low[x]=min(low[x],low[k]); }else if(in[k]==true) { low[x]=min(low[x],dfn[k]); } } if(low[x]==dfn[x]) { int k; do { k=st.top(); st.pop(); in[k]=false; f[k]=x; }while(k!=x); } } bool solve(int d,int s) { memset(head,-1,sizeof(head)); I=0; for(int i=1;i<=n;++i) { for(int j=1;j<i;++j) { int w=0; if(Adist[i]+Adist[j]>d) {build(i,j+n);build(j,i+n);++w;} if(Bdist[i]+Bdist[j]>d) {build(i+n,j);build(j+n,i);++w;} if(Adist[i]+Bdist[j]+s>d) {build(i,j);build(j+n,i+n);++w;} if(Bdist[i]+Adist[j]+s>d) {build(i+n,j+n);build(j,i);++w;} if(w==4) return false; } } for(int l=1;l<=m1;++l) { build(hate[l].i,hate[l].j+n);build(hate[l].j,hate[l].i+n); build(hate[l].i+n,hate[l].j);build(hate[l].j+n,hate[l].i); } for(int l=1;l<=m2;++l) { build(fri[l].i,fri[l].j);build(fri[l].j,fri[l].i); build(fri[l].i+n,fri[l].j+n);build(fri[l].j+n,fri[l].i+n); } memset(visited,false,sizeof(visited)); memset(in,false,sizeof(in)); memset(f,-1,sizeof(f)); while(!st.empty()) st.pop(); deep=0; int l; for(l=1;l<n;++l) { if(!visited[l]) Tarjan(l); if(f[l]!=-1&&f[l]==f[l+n]) break; } if(l<n) return false; else return true; } int main() { //freopen("data.txt","r",stdin); while(scanf("%d %d %d",&n,&m1,&m2)!=EOF) { int sx1,sy1,sx2,sy2; scanf("%d %d %d %d",&sx1,&sy1,&sx2,&sy2); int s=abs(sx1-sx2)+abs(sy1-sy2); for(int i=1;i<=n;++i) { int x,y; scanf("%d %d",&x,&y); Adist[i]=abs(x-sx1)+abs(y-sy1); Bdist[i]=abs(x-sx2)+abs(y-sy2); } int L=0; for(int i=1;i<=n;++i) { for(int j=1;j<i;++j) { ans[++L]=Adist[i]+Adist[j]; ans[++L]=Bdist[i]+Bdist[j]; ans[++L]=Adist[i]+Bdist[j]+s; ans[++L]=Bdist[i]+Adist[j]+s; } } for(int i=1;i<=m1;++i) scanf("%d %d",&hate[i].i,&hate[i].j); for(int i=1;i<=m2;++i) scanf("%d %d",&fri[i].i,&fri[i].j); sort(ans+1,ans+L+1); int l=1,r=L; while(l<r) {//cout<<l<<" "<<r<<endl; int mid=(l+r)/2; if(solve(ans[mid],s)) r=mid; else l=mid+1; } if(!solve(ans[r],s)) printf("-1\n"); else printf("%d\n",ans[r]); } return 0; }