poj 2749 Building roads

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;

}

  

你可能感兴趣的:(Build)