POJ 2749 Building roads【二分+2-sat】

题意: 已知有 n 个农场,知道了每个农场的坐标,有两个中转站 s1,s2, 每个农场和其中一个中转站相连,

         有 A 对hate关系 a,b 表示 a 和 b 农场不能和同一个中转站相连,

         有 B 对Fs   关系 a,b 表示  a 和 b 农场必须和同一个中转站相连,  

         求一种连接方案,在满足条件 A,B的条件下,图中任意两个农场的最大距离最小。

分析: i 表示第 i 个农场和中转站 s1 相连,i + n 表示第 i 个农场和中转站 s2 相连,

     建图:         

        在 A 条件中,对于每对关系 i , j 连边

        i       -> j + n

        i + n -> j

        j       ->i + n

        j + n ->i

        表示 i 和 j 不能和同一个中转站相连

        在 B 条件中,对于没对关系的建边方式和上面类似,

        对每一次枚举的 距离 di,

        枚举任意两个农场 i , j

        如果 距离 i->s1->j 大于 di ,       连边 

        i -> j+n      ,   j -> i+n   表示 i , j 农场不能同时和 s1 相连

        如果 距离 i->s2->j 大于 di ,       连边 

        i + n -> j    ,   j + n -> i 表示 i , j 农场不能同时和 s2 相连

        如果 距离 i->s1->s2->j 大于 di ,连边 

        i -> j   ,  j + n -> i + n 表示 如果 i 农场和 s1 相连,则 j 农场必须和 s1 相连,如果 j 农场和 s2 相连,则 i 必须和s2 相连

        如果 距离 i->s2->s1->j 大于 di ,连边 

        j -> i   ,  i + n -> j + n 表示 如果 j 农场和 s1 相连,则 i 农场必须和 s1 相连,如果 i 农场和 s2 相连,则 j 必须和s2 相连

        对于每次枚举的距离 di 判断是否有冲突情况即可。

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
#define min(a,b)(a)<(b)?(a):(b)
#define max(a,b)(a)>(b)?(a):(b)
#define maxn 1005
#define maxm 1000000
struct node
{
    int to,next;
}e[maxm];
int tot;
int head[maxn];
void add(int s,int t)
{
    e[tot].to=t;
    e[tot].next=head[s];
    head[s]=tot++;
}
int ti,sn,top,n;
int dfn[maxn];
int low[maxn];
int ins[maxn];
int sta[maxn];
int col[maxn];
void tarjan(int u)
{
    dfn[u]=low[u]=++ti;
    ins[u]=1;
    sta[++top]=u;
    int i,k;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(dfn[k]==0)
        {
            tarjan(k);
            low[u]=min(low[u],low[k]);
        }
        else if(ins[k])
            low[u]=min(low[u],dfn[k]);
    }
    if(dfn[u]==low[u])
    {
        sn++;
        do
        {
            k=sta[top--];
            ins[k]=0;
            col[k]=sn;
        }while(k!=u);
    }
}
struct point
{
    int x,y;
}p[maxn],s1,s2;
int ab(int x)
{  return x>0?x:-x; }
int dis(point a,point b)
{
    return ab(a.x-b.x)+ab(a.y-b.y);
}
struct Fs
{
    int a,b;
}hate[1005],fs[1005];
int A,B;
int g[505][505];
bool ok(int di)    
{
    tot=1;
    clr(head);
    int i,j;
    for(i=1;i<=A;i++)
    {
        add(hate[i].a,hate[i].b+n);
        add(hate[i].a+n,hate[i].b);
        add(hate[i].b,hate[i].a+n);
        add(hate[i].b+n,hate[i].a);
    }
    for(i=1;i<=B;i++)
    {
        add(fs[i].a,fs[i].b);
        add(fs[i].a+n,fs[i].b+n);
        add(fs[i].b,fs[i].a);
        add(fs[i].b+n,fs[i].a+n);
    }
    for(i=1;i<=n;i++)
        for(j=i+1;j<=n;j++)
        {
            if(g[0][i]+g[0][j]>di)
                add(i,j+n),add(j,i+n);
            if(g[i][0]+g[j][0]>di)
                add(i+n,j),add(j+n,i);
            if(g[0][i]+g[0][0]+g[j][0]>di)
                add(i,j),add(j+n,i+n);
            if(g[0][j]+g[0][0]+g[i][0]>di)
                add(j,i),add(i+n,j+n);
        }
    sn=top=ti=0;
    clr(dfn);
    for(i=1;i<=2*n;i++)
        if(!dfn[i])
            tarjan(i);
    for(i=1;i<=n;i++)
        if(col[i]==col[i+n])
            return 0;
    return 1;
}
int main()
{
    int i,j,k;
    while(scanf("%d%d%d",&n,&A,&B)!=EOF)
    {
        scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y);
        for(i=1;i<=n;i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        int l=0,r=5000000,mid,res;
        for(i=1;i<=n;i++)
            for(j=i+1;j<=n;j++)
                g[i][j]=g[j][i]=dis(p[i],p[j]);
        for(i=1;i<=n;i++)
        {
            g[0][i]=dis(s1,p[i]);
            g[i][0]=dis(p[i],s2);
        }
        g[0][0]=dis(s1,s2);
        for(i=1;i<=A;i++)
            scanf("%d%d",&hate[i].a,&hate[i].b);
        for(i=1;i<=B;i++)
            scanf("%d%d",&fs[i].a,&fs[i].b);
        res=-1;
        while(l<=r)
        {
            mid=(l+r)>>1;
            if(ok(mid))
            {    
                res=mid;
                r=mid-1;
            }
            else 
                l=mid+1;
        }
        printf("%d\n",res);
    }
    return 0;
}

 

posted @ 2012-10-01 14:49  'wind  阅读(164)  评论(0编辑  收藏  举报