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;
}

  

posted on 2012-08-18 17:02  夜->  阅读(204)  评论(0编辑  收藏  举报