Poj2749 Building Roads

来源:互联网 发布:简约博客源码 编辑:程序博客网 时间:2024/06/03 19:23

有N个点,每个点向S1或S2连边。有一些恩怨情仇限制某些对点不能同时连向同一点,而某些对点必须同时连向同一点。每个点到S1和S2都有距离,我们要求可行方案中最大的两点间通过所连的S1(S2)到达彼此的距离最小是多少。

除了恩怨情仇外的限制再加上二分出的距离的限制来做2-SAT判定就好了。

#include<cmath>#include<stack>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>using namespace std;struct edge {    int x,y,next;    edge(){}    edge(int _x,int _y,int _nt):x(_x),y(_y),next(_nt){}} e[ 1000005 ];int head[2000],tot = 0;inline void addedge(int x,int y) {    e[++tot] = edge(x,y,head[x]); head[x] = tot;}bool ins[2000];int inc[2000],dfn[2000],low[2000],SCC,T;stack<int>sta;void tarjan(int x){    dfn[x] = low[x] = ++T;    sta.push(x); ins[x] = 1;    for (int i = head[x]; i; i = e[i].next) {        int y = e[i].y;        if( ! dfn[y] ) {            tarjan(y);            low[x] = min(low[x], low[y]);        }else if( ins[y] && dfn[y] < low[x]) low[x] = dfn[y];    }    if( low[x] == dfn[x] ){        SCC++;        while(1) {            int y = sta.top(); sta.pop(); ins[y] = 0;            inc[y] = SCC;            if (x == y ) break;        }    }}struct point {    int x,y;    point(){}    point(int _x,int _y):x(_x),y(_y){}} a[2005],s[3];int dis(point a,point b) {    return abs(a.x-b.x) + abs(a.y-b.y);}int N,A,B;int e1[2005][2],e2[2005][2];int d1[2005],d2[2005],d12;bool judge(int d) {    memset(head,0,sizeof head);    tot = 0;    for (int i = 1; i <= A; i++) {        addedge(e1[i][0],   e1[i][1]+N);        addedge(e1[i][0]+N, e1[i][1]);        addedge(e1[i][1],   e1[i][0]+N);        addedge(e1[i][1]+N, e1[i][0]);    }    for (int i = 1; i <= B; i++) {        addedge(e2[i][0],   e2[i][1]);        addedge(e2[i][0]+N, e2[i][1]+N);        addedge(e2[i][1],   e2[i][0]);        addedge(e2[i][1]+N, e2[i][0]+N);    }    for (int i = 1; i <= N; i++) for (int j = i+1; j <= N; j++) {        if ( d1[i] + d1[j] > d ) {            addedge(i,j+N);                     addedge(j,i+N);        }        if ( d2[i] + d2[j] > d ) {            addedge(i+N,j);            addedge(j+N,i);        }         if ( d1[i] + d12 + d2[j] > d ) {            addedge(i,j); addedge(j+N,i+N);        }        if ( d2[i] + d12 + d1[j] > d ) {            addedge(i+N,j+N); addedge(j,i);        }     }    SCC = 0; T = 0;    memset(ins,0,sizeof ins);    memset(dfn,0,sizeof dfn);    for (int i = 1; i <= N<<1; i++) if( ! dfn[i] ) tarjan(i);    for (int i = 1; i <= N; i++)        if( inc[i] == inc[i+N] ) return 0;    return 1;}int main() {    scanf("%d%d%d",&N,&A,&B);    scanf("%d%d%d%d",&s[1].x,&s[1].y,&s[2].x,&s[2].y);    int L = 0x3f3f3f3f,R = -1 ,mid,ans;    d12 = dis(s[1],s[2]);    for (int i = 1; i <= N; i++) {        scanf("%d%d",&a[i].x,&a[i].y);        d1[i] = dis(a[i], s[1]);        d2[i] = dis(a[i], s[2]);        L = min(L,min(d1[i],d2[i]));        R = max(R,max(d1[i],d2[i]));    }    L <<= 1, (R<<=1)+= d12, ans = 0x3f3f3f3f;    for (int i = 1; i <= A; i++) scanf("%d%d",&e1[i][0],&e1[i][1]);    for (int i = 1; i <= B; i++) scanf("%d%d",&e2[i][0],&e2[i][1]);    while( L <= R) {        int mid = (L + R) >> 1;        if( judge(mid) ) ans = mid,R=mid-1;        else L = mid + 1;    }    if( ans == 0x3f3f3f3f ) ans = -1;    printf("%d\n",ans);}
0 0