1 /*LA3211
2 2-sat+二分答案
3 现在统一建模的方式:
4 1、同一组的两个状态分别存储在2*i和2*i+1两个节点,产生2*n个节点
5 2、for(int i=1;i<2*n;i++)
6 for(int j=0;j<i;j++)
7 {
8 if (i==(j^1)) continue;
9 sat.add_clause(i,j);//枚举出的不属于同一组的不相容的两点
10 }
11 3、2-sat即可
12 和HDU3622相似
13 */
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <math.h>
18 #include <ctype.h>
19 #include <string>
20 #include <iostream>
21 #include <sstream>
22 #include <vector>
23 #include <queue>
24 #include <stack>
25 #include <map>
26 #include <list>
27 #include <set>
28 #include <algorithm>
29 #define INF 0x3f3f3f3f
30 #define LL long long
31 #define eps 1e-4
32 #define maxn 2010
33 using namespace std;
34 int T[2*maxn];
35 struct TwoSAT
36 {
37 int n;
38 vector<int> G[maxn*2];
39 bool mark[maxn*2];//联系《2-sat算法解析》中的红蓝标色
40 int S[maxn*2],c;
41 bool dfs(int x)
42 {
43 if (mark[x^1]) return false;//真假同时被标记,逻辑矛盾
44 if (mark[x]) return true;//x被标记,意味着下面的节点也被标记,思想是记忆化搜索
45 mark[x]=true;
46 S[c++]=x;
47 for(int i=0; i<G[x].size(); i++)
48 if(!dfs(G[x][i])) return false; //同一个强联通分量应该表上同一种颜色
49 return true;
50 }
51 void init(int n)
52 {
53 this->n=n;
54 for(int i=0; i<n*2; i++) G[i].clear();
55 memset(mark,0,sizeof(mark));
56 }
57 //x=xval or y=xval ,x 则 xval=0,x'则xval=1
58 void add_clause(int x ,int y)
59 {
60 G[x].push_back(y^1);
61 G[y].push_back(x^1);
62 }
63 bool solve()
64 {
65 for(int i=0;i<n*2;i+=2)
66 {
67 if(!mark[i] && !mark[i^1])//真假都没被标记才需dfs,思考一下,原书上写的是[mark+1],这是由i的取值和步长决定的,这里更改,使逻辑含义统一
68 {
69 c=0;//记得清零
70 if(!dfs(i))//将i标记为true
71 {
72 while(c>0) mark[S[--c]]=false;
73 if (!dfs(i^1)) return false;//更改初始标号颜色。只要有一个对象不能“二选一”,则2-sat无解
74 }
75 }
76 }
77 return true;
78 }
79 } sat;
80 double dis(double x1,double y1,double x2,double y2)
81 {
82 return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
83 }
84 int n;
85 bool solve(int time)
86 {
87 sat.init(n);
88 for(int i=1;i<2*n;i++)//枚举
89 {
90 for(int j=0;j<i;j++)
91 {
92 if (i==(j^1)) continue;//消除所有的同一组的
93 if (time>abs(T[i]-T[j])) sat.add_clause(i,j);
94 }
95 }
96 return sat.solve();
97 }
98 int nextint(){int x;scanf("%d",&x);return x;}
99 int main()
100 {
101 while(cin>>n)
102 {
103 for(int i=0;i<n;i++)
104 {
105 T[i*2]=nextint();
106 T[i*2+1]=nextint();
107 }
108 int L=0,R=10000001;
109 while(R>L)
110 {
111 int M=(L+R+1)/2;
112 if (!solve(M)) R=M-1;else L=M;
113 }
114 cout<<L<<endl;
115 //貌似printf不能配合ceil使用 = =~
116 //最终结果要求是整数,要满足实际意义
117 }
118 return 0;
119 }