POJ_2749 Building roads 2-Sat

来源:互联网 发布:json 汉字解析不出来 编辑:程序博客网 时间:2024/05/17 09:06

http://poj.org/problem?id=2749

题意:

有N个牛棚,2个中转站,每个牛棚只能选择一个中转站并连接到该中转站,求任意

两个在同一个中转站中的牛棚之间的最大距离的最小值。 

思路:

"最大值最小化"的问题都可以用“二分法”,本题也不例外,其次就是建图用2-sat求解,

建图的规则是:

如果d1[i] + d1[j] > mid 则说明i号牛棚和j号牛棚不能同时连接到0号中转站,则加边(i , j+N) ;

d1[i] + d2[j] + D > mid 则说明i号牛棚连0时,j号牛棚不能连j ,加边(i , j)

d2[i] + d1[j] + D > mid , 同理加边 (i+N ,j + N)  ;

d2[i] + d2[j] > mid    加边 (i+N, j) ;

最后还需要加上hate和like 的条件。


总结:2-Sat问题建图的时候,可以通过找不能满足的条件来建图,即通过找到一组不可能的情况从而推出一组确定的边 。


代码:

#include<stdio.h>#include<string.h>#include<math.h>#include<stdlib.h>int N ,A, B , D;int sx[2] , sy[2] ;int x[550] , y[550] ;const int MAXN = 510*2 ;int Gv[MAXN*MAXN] , Gnext[MAXN*MAXN] , Gr[MAXN]  ,Gc ;int dfn[MAXN] , low[MAXN]  ,stack[MAXN] , belong[MAXN] ;int top ,idx , Bcnt ;bool hate[510][510] , in[MAXN];bool like[510][510] ;int d1[MAXN] , d2[MAXN] ;void add(int a, int b){    Gv[Gc] = b ;    Gnext[Gc] = Gr[a] ;    Gr[a] = Gc++ ;}void tarjin(int u){    int v ;    low[u] = dfn[u] = ++idx ;    stack[++top] = u ; in[u] = 1 ;    for(int i=Gr[u] ;i!=-1;i=Gnext[i]){        v = Gv[i] ;        if( !dfn[v] ){            tarjin(v) ;            if( low[v] < low[u])                low[u] = low[v] ;        }        else if(in[v] && dfn[v] < low[u])            low[u] = dfn[v] ;    }    if( low[u] == dfn[u] ){        Bcnt++ ;        do{            v = stack[top--] ;  in[v] = 0 ;            belong[v] = Bcnt ;        }while(u != v) ;    }}int MAX(int a, int b){    return a > b ? a : b ;}bool solve(int mid){    memset(Gr , -1 ,sizeof(Gr)) ;    Gc = 0 ;    for(int i=1;i<=N;i++){        for(int j=1;j<=N;j++){            if(i == j)  continue ;            if( d1[i] + d1[j] > mid ){                add(i , j+N);            }            if( d1[i] + d2[j] + D > mid){                add(i , j);            }            if( d2[i] + d1[j] + D > mid){                add(i+N, j+N);            }            if( d2[i] + d2[j] > mid){                add(i+N,j);            }            if(hate[i][j] == 1 ){                add(i,j+N);                add(i+N,j);            }            if( like[i][j] == 1){                add(i,j) ;                add(i+N,j+N);            }        }    }    top = idx = Bcnt = 0 ;    memset(dfn , 0 ,sizeof(dfn));    memset(in, 0, sizeof(in)) ;    for(int i=1;i<=2*N;i++){        if( !dfn[i] )   tarjin(i) ;    }    for(int i=1;i<=N;i++){        if( belong[i] == belong[i+N] )  return false ;    }    return true ;}void deal(){    int l , h , m ;    l = 0 ; h = 5000000 ;    while( l < h ){        m = (l + h) >> 1 ;        if( solve(m) ){            h = m ;        }        else            l = m + 1 ;    }    if(l == 5000000 )        printf("-1\n");    else        printf("%d\n",l) ;}int main(){    int a ,b ;    while(scanf("%d%d%d",&N,&A,&B) == 3){        for(int i=0;i<2;i++)    scanf("%d%d",&sx[i],&sy[i]);        D = abs(sx[0] - sx[1]) + abs(sy[0] - sy[1]);        for(int i=1;i<=N;i++){            scanf("%d%d",&x[i],&y[i]);        }        memset(hate , 0 ,sizeof(hate));        memset(like, 0,sizeof(like)) ;        for(int i=1;i<=A;i++){            scanf("%d%d",&a,&b);            hate[a][b] = hate[b][a] = 1;        }        for(int i=1;i<=B;i++){            scanf("%d%d",&a,&b);            like[a][b] = like[b][a] = 1 ;        }        for(int i=1;i<=N;i++){            d1[i] = abs( x[i] - sx[0] ) + abs( y[i] - sy[0] ) ;            d2[i] = abs( x[i] - sx[1] ) + abs( y[i] - sy[1] ) ;        }        deal() ;    }    return 0 ;}

原创粉丝点击