POJ 2749 Building roads (2-SAT)

来源:互联网 发布:并行计算的编程模型 编辑:程序博客网 时间:2024/05/22 02:33

题意:

农场主的牛喜欢串门。。。(又一道奇葩题目。。)
所以农场主得给他的n个牛舍(barn)建造道路,然而农场主觉得花费太多,所以他打算建造两个中转点s1和s2,任意的牛舍要么连s1,要么连s2。
同时还有一些牛舍里的互相讨厌,所以这两个牛舍不能连到同一个中转站。
同时还有一些牛舍里的互相喜欢,所以这两个牛舍要连到同一个中转站。
给你s1和s2的坐标,然后还有n个牛舍的坐标,问你,让牛舍之间的最大距离最短的方案的距离是多少。
距离算的是曼哈顿距离。

思路:

二分距离,每次根据新的距离建边(通过矛盾建立必选关系)。
由于我使用的是链式前向星,所以我保存了cnte和head数组,每次只要在这个基础上建边就好了,不必再动喜欢和讨厌关系建立的边。

撒花完结~2-SAT的7道题都刷穿了23333

#include <iostream>#include <algorithm>#include <cstdio>#include <string.h>#include <queue>#include <cmath>#define pi acos(-1.0)#define eps 1e-6typedef long long int lli;using namespace std;const int maxn = 4200;struct edge{    int from,to,v,next;}ed[2000000];struct node{    int x,y;}no[600],ha[1200],lo[1200];node s[2];int t,a,b;int head[maxn];int jiluh[maxn];int cnte,jilu;void ae(int x,int y){    ed[++cnte].to = y;    ed[cnte].next = head[x];    head[x]=cnte;}int dfn[maxn],low[maxn],vis[maxn],stak[maxn],belong[maxn],cntc,cnts,index;//strong connected component //cnt of stackvoid dfs(int u){    dfn[u]=low[u] = ++index;    stak[cnts++]=u;    vis[u]=1;    for(int i = head[u];i!=-1;i=ed[i].next){        int v = ed[i].to;        if(!dfn[v]){            dfs(v);            low[u] = min(low[u],low[v]);        }        else if(vis[v]){            low[u] = min(low[u],dfn[v]);        }    }    if(dfn[u]==low[u]){        cntc++;int v;        do{            v = stak[--cnts];            vis[v] = 0;            belong[v] = cntc;        }while(v!=u);    }}int n,m;void tarjan(){    for(int i = 1;i <= 2*n;i++){        if(!dfn[i]){            dfs(i);        }    }}double dis(node a,node b){    return ( abs(a.x-b.x) + abs(a.y-b.y) );}void ini(){    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(vis,0,sizeof(vis));    memset(belong,0,sizeof(belong));    cntc=index=0;}bool jud(){    for(int i = 1;i <= n;i++){        if(belong[i]!=0 &&belong[i] == belong[i+n]){            return false;        }    }    return true;}bool build(int mid){    cnte = jilu;    for(int i = 1;i <= 2*n;i++){        head[i] = jiluh[i];    }    for(int i = 1;i <= n;i++){        for(int j = 1;j <= n;j++){            if(i!=j){                if(dis(no[i],s[0])+dis(no[j],s[0]) >mid){                    ae(i,j+n);ae(j,i+n);                }                if(dis(no[i],s[1])+dis(no[j],s[1]) >mid){                    ae(i+n,j);ae(j+n,i);                }                if(dis(no[i],s[0])+dis(no[j],s[1])+dis(s[0],s[1]) >mid){                    ae(i,j);ae(j+n,i+n);                }                if(dis(no[i],s[1])+dis(no[j],s[0])+dis(s[0],s[1])>mid){                    ae(i+n,j+n);ae(j,i);                }            }        }    }    ini();tarjan();    if(!jud()){        return false;    }    return true;}int main(){    scanf("%d%d%d",&n,&a,&b);    memset(head,-1,sizeof(head));cnte = 0;    scanf("%d%d%d%d",&s[0].x,&s[0].y,&s[1].x,&s[1].y);    for(int i = 1;i <= n;i++){        scanf("%d%d",&no[i].x,&no[i].y);    }    for(int i = 1;i <= a;i++){        scanf("%d%d",&ha[i].x,&ha[i].y);        ae(ha[i].x,ha[i].y+n);ae(ha[i].y,ha[i].x+n);        ae(ha[i].y+n,ha[i].x);ae(ha[i].x+n,ha[i].y);    }    for(int i = 1;i <= b;i++){        scanf("%d%d",&lo[i].x,&lo[i].y);        ae(lo[i].x,lo[i].y);ae(lo[i].x+n,lo[i].y+n);        ae(lo[i].y,lo[i].x);ae(lo[i].y+n,lo[i].x+n);    }    jilu = cnte;    for(int i  = 1;i <= 2*n;i++){        jiluh[i] = head[i];    }    tarjan();    if(!jud()){        printf("-1\n");return 0;    }    int mid,l = 1,r = 4000000;    while(l < r){        mid = (l+r)/2;        if(build(mid)){            r = mid;        }        else{            l = mid+1;        }    }    printf("%d\n",r);}