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 ;}
- POJ_2749 Building roads 2-Sat
- poj2749 Building roads 2-sat
- HDU1815 Building roads (2-SAT)
- POJ2749 Building roads【2-SAT】
- poj 2749 Building roads #二分+2-sat
- POJ 2749 Building roads (2-sat)
- 2-sat->poj 2479 Building roads
- POJ 2749 Building roads(2-SAT)
- 【HDU】1822 Building roads 2-sat
- 【2-sat】 HDOJ 1815 Building roads
- poj 2749 Building roads 2-sat
- POJ 2749 - Building roads(2-SAT+二分)
- poj 2749 Building roads 2-SAT
- HDU - 1815 Building roads (2-SAT)
- |poj 2749|2-SAT|二分|Building roads
- poj2749:Building roads(2-SAT)
- POJ 2749 Building roads (2-SAT)
- 2-SAT——6.0(poj2749 Building roads)
- 如何在后台代码中执行原生sql?
- Google Web App开发指南第四章:构建优秀的Web Apps
- android string.xml中的string样式总结
- KSQL中Update多表级联更新的语法
- SSH
- POJ_2749 Building roads 2-Sat
- F7增加值改变事件
- VS2010实现类似EditPlus目录视图
- 当你输入一个网址的时候,实际会发生什么?
- 某高人整理的Java就业面试题大全【3】
- 2.11-在顺序表va中插入x使仍然有序
- 杭电2001 求两点间的距离
- DP问题
- A*算法求解8数码问题