2-SAT——6.0(poj2749 Building roads)

来源:互联网 发布:网络好听的歌曲排行榜 编辑:程序博客网 时间:2024/06/06 20:58

poj2749 Building roads

题意是说有 N 个牛栏,现在通过一条通道(s1,s2)把他们连起来,他们之间有一些约束关系,一些牛栏不能连在同一个点,一些牛栏必须连在同一个点,现在问有没有可能把他们都连好,而且满足所有的约束关系,如果可以,输出两个牛栏之间距离最大值的最小情况。

比如牛栏 A 连在 s1 点,牛栏 B 连在 s2 点,那么AB之间的距离为(As1 + s1s2 + s2B);也可以两个牛栏连在同一个点上,比如 A 连在 s1 ,B 也连在 s1 ,那么AB的距离是(As1 + Bs1)。

A 表示连在s1,A‘ 表示连在 s2 ,按照给出的约束关系建边,然后在区间内2分枚举所有可能的解 ans,如果当前解满足条件,那么就意味着 ans 还可以更小,如果不满足,说明当前的 ans 值过大。

#include<iostream>#include<cstdio>#include<cstring>#include<stack>#include<cmath>#include<climits>#define find_min(a,b) (a<b?a:b)#define find_max(a,b) (a>b?a:b)using namespace std;const int N = 2010;struct point{int x,y;};point p[N];struct Edge{int s,e,next;}edge[5*N];int n,e_num,vis_num,cnt,head[N],instack[N],low[N],tim[N],belong[N];void AddEdge(int a,int b){edge[e_num].s=a; edge[e_num].e=b; edge[e_num].next=head[a]; head[a]=e_num++;}int dis_m(point a,point b){return abs(a.x-b.x)+abs(a.y-b.y);}stack <int>st;void tarjan(int x){    int i;    tim[x]=low[x]=++vis_num;    instack[x]=1;    st.push(x);    for(i=head[x];i!=-1;i=edge[i].next){        int u=edge[i].e;        if(tim[u]==-1){            tarjan(u);            if(low[x]>low[u])low[x]=low[u];        }        else if(instack[u] && low[x]>tim[u])low[x]=tim[u];    }    if(low[x]==tim[x]){        cnt++;        do{            i=st.top();            st.pop();            instack[i]=0;            belong[i]=cnt;        }while(i!=x);    }}void init(){vis_num=cnt=0;    memset(instack,0,sizeof(instack));    memset(belong,-1,sizeof(belong));    memset(tim,-1,sizeof(tim));    memset(low,0,sizeof(low));}int main(){int A,B;int i,j,left,right,mid,ans;int hate[N][2],like[N][2];point s1,s2;while(~scanf("%d%d%d",&n,&A,&B)){scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y);int len=dis_m(s1,s2);int min=INT_MAX;int max=INT_MIN;for(i=0;i<n;i++){scanf("%d%d",&p[i].x,&p[i].y);min=find_min(min, find_min(dis_m(p[i],s1),dis_m(p[i],s2)) );max=find_max(max, find_max(dis_m(p[i],s1),dis_m(p[i],s2)) );}for(i=0;i<A;i++){scanf("%d%d",&hate[i][0],&hate[i][1]);hate[i][0]--; hate[i][1]--;}for(i=0;i<B;i++){scanf("%d%d",&like[i][0],&like[i][1]);like[i][0]--; like[i][1]--;}left=2*min; right=2*max+len; ans=INT_MAX;while(left<=right){e_num=0;memset(head,-1,sizeof(head));for(i=0;i<A;i++){AddEdge(2*hate[i][0],2*hate[i][1]+1);AddEdge(2*hate[i][0]+1,2*hate[i][1]);AddEdge(2*hate[i][1],2*hate[i][0]+1);AddEdge(2*hate[i][1]+1,2*hate[i][0]);}for(i=0;i<B;i++){AddEdge(2*like[i][0],2*like[i][1]);AddEdge(2*like[i][0]+1,2*like[i][1]+1);AddEdge(2*like[i][1],2*like[i][0]);AddEdge(2*like[i][1]+1,2*like[i][0]+1);}mid=(left+right)/2;for(i=0;i<n;i++){for(j=i+1;j<n;j++){if(i!=j){if(dis_m(p[i],s1)+dis_m(p[j],s1)>mid){//点 i 到 s1 的距离加上点 j 到 s1 的距离大于所枚举的最大值,所以矛盾AddEdge(2*i,2*j+1);AddEdge(2*j,2*i+1);}if(dis_m(p[i],s2)+dis_m(p[j],s2)>mid){AddEdge(2*i+1,2*j);AddEdge(2*j+1,2*i);}if(dis_m(p[i],s1)+dis_m(p[j],s2)+len>mid){AddEdge(2*i,2*j);AddEdge(2*j+1,2*i+1);}if(dis_m(p[j],s1)+dis_m(p[i],s2)+len>mid){AddEdge(2*j,2*i);AddEdge(2*i+1,2*j+1);}}}}init();for(i=0;i<2*n;i++){if(tim[i]==-1)tarjan(i);}int flag=1;for(i=0;i<n;i++){if(belong[2*i]==belong[2*i+1]){flag=0;break;}}if(flag){ans=find_min(mid,ans); right=mid-1;}else left=mid+1;}printf("%d\n",ans<INT_MAX?ans:-1);}return 0;}