Poj--2296(2-SAT,二分)
2014-10-19 13:55:03
思路:典型的2分+2-SAT,给题目数据范围跪了,之前RE到寺,我开到1000才过QAQ。
首先二分边长d 。
建图:分类讨论,如果两点间x坐标绝对值差>=d则不用建边,如果x坐标绝对值<d,则分:(1)y坐标绝对值差>=2d不用建边(2)y坐标绝对值差<2d且>=d(3)y坐标绝对值差<d且>0(4)y绝对值差 == 0 (这种情况一定要考虑到。)
1 /************************************************************************* 2 > File Name: 2296.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sat 18 Oct 2014 06:24:02 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 1000; 27 28 int n,m,t; 29 int x[maxn],y[maxn]; 30 int low[maxn],dfn[maxn],sc[maxn],scnt,tot; 31 int first[maxn],next[maxn * maxn],ver[maxn * maxn],ecnt; 32 stack<int> S; 33 34 void Add_edge(int u,int v){ 35 next[++ecnt] = first[u]; 36 ver[ecnt] = v; 37 first[u] = ecnt; 38 } 39 40 void Dfs(int p){ 41 dfn[p] = low[p] = ++tot; 42 S.push(p); 43 for(int i = first[p]; i != -1; i = next[i]){ 44 int v = ver[i]; 45 if(!dfn[v]){ 46 Dfs(v); 47 low[p] = min(low[p],low[v]); 48 } 49 else if(!sc[v]){ 50 low[p] = min(low[p],dfn[v]); 51 } 52 } 53 if(low[p] == dfn[p]){ 54 ++scnt; 55 while(1){ 56 int tem = S.top(); 57 S.pop(); 58 sc[tem] = scnt; 59 if(tem == p) break; 60 } 61 } 62 } 63 64 void Tarjan(){ 65 memset(low,0,sizeof(low)); 66 memset(dfn,0,sizeof(dfn)); 67 memset(sc,0,sizeof(sc)); 68 while(!S.empty()) S.pop(); 69 scnt = tot = 0; 70 for(int i = 0; i < 2 * m; ++i) 71 if(!dfn[i]) Dfs(i); 72 } 73 74 void Init(){ 75 memset(first,-1,sizeof(first)); 76 } 77 78 bool Solve(int val){ 79 //Build graph 80 Init(); 81 int dx,dy; 82 for(int i = 0; i < m; ++i){ 83 for(int j = i + 1; j < m; ++j){ 84 dx = abs(x[i] - x[j]); 85 dy = abs(y[i] - y[j]); 86 if(dx < val){ 87 if(dy < 2 * val){ 88 if(dy >= val){ 89 if(y[i] > y[j]){ 90 Add_edge(i * 2 + 1,j * 2 + 1); 91 Add_edge(j * 2,i * 2); 92 } 93 else{ 94 Add_edge(j * 2 + 1,i * 2+ 1); 95 Add_edge(i * 2,j * 2); 96 } 97 } 98 else if(dy > 0){ 99 if(y[i] > y[j]){ 100 Add_edge(i * 2,j * 2 + 1); 101 Add_edge(i * 2 + 1,i * 2); 102 Add_edge(j * 2 + 1,i * 2); 103 Add_edge(j * 2,j * 2 + 1); 104 } 105 else{ 106 Add_edge(j * 2,i * 2 + 1); 107 Add_edge(j * 2 + 1,j * 2); 108 Add_edge(i * 2 + 1,j * 2); 109 Add_edge(i * 2,i * 2 + 1); 110 } 111 } 112 else{ 113 Add_edge(i * 2,j * 2 + 1); 114 Add_edge(j * 2 + 1,i * 2); 115 Add_edge(i * 2 + 1,j * 2); 116 Add_edge(j * 2,i * 2 + 1); 117 } 118 } 119 } 120 } 121 } 122 Tarjan(); 123 for(int i = 0; i < 2 * m; i += 2){ 124 if(sc[i] == sc[i + 1]) 125 return false; 126 } 127 return true; 128 } 129 130 int main(){ 131 scanf("%d",&t); 132 while(t--){ 133 scanf("%d",&m); 134 for(int i = 0; i < m; ++i) 135 scanf("%d%d",x + i,y + i); 136 int mid,l = 0,r = 20001,ans; 137 while(l < r){ 138 mid = l + (r - l) / 2; 139 if(Solve(mid)){ 140 ans = mid; 141 l = mid + 1; 142 } 143 else 144 r = mid; 145 } 146 printf("%d\n",ans); 147 } 148 return 0; 149 }