POJ 2296 Map Labeler (二分+2-SAT判)

http://poj.org/problem?id=2296

很好的一道2-SAT题

取上为1,取下为0

两个新规则:

a = 0: 这个等价于加边!a->a

a = 1: 这个等价于加边a->!a

 

当二者y差值<r时,y大的在上,y小的在下

如果等于r时,取i xor j = 1

如果大于r小于2r,则y大的在下,y小的在上这种情况不能存在(and = 0)

其他情况怎么放都可以

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<string>
  6 #include<cmath>
  7 #include<set>
  8 #include<list>
  9 #include<map>
 10 #include<iterator>
 11 #include<cstdlib>
 12 #include<vector>
 13 #include<queue>
 14 #include<stack>
 15 #include<algorithm>
 16 #include<functional>
 17 using namespace std;
 18 typedef long long LL;
 19 #define ROUND(x) round(x)
 20 #define FLOOR(x) floor(x)
 21 #define CEIL(x) ceil(x)
 22 const int maxn=110;
 23 const int maxm=0;
 24 const int inf=0x3f3f3f3f;
 25 const LL inf64=0x3f3f3f3f3f3f3f3fLL;
 26 const double INF=1e30;
 27 const double eps=1e-6;
 28 
 29 /**
 30 *2-SAT模板,Modified Edition of LRJ 按字典序排列结果
 31 *输入:按照法则添加边(参数为2*i或者2*i+1)
 32 *运行:先init(n),再add(),再solve()
 33 *注意:add(2*i,2*j)才行
 34 *输出:mark[](1表示选中),solve()(是否有解)
 35 */
 36 //const int maxn = 0;
 37 struct TwoSAT
 38 {
 39     int n;
 40     vector<int> G[maxn*2];
 41     bool mark[maxn*2];
 42     int S[maxn*2], c;
 43 
 44     bool dfs(int x)
 45     {
 46         if (mark[x^1]) return false;
 47         if (mark[x]) return true;
 48         mark[x] = true;
 49         S[c++] = x;
 50         for (int i = 0; i < G[x].size(); i++)
 51             if (!dfs(G[x][i])) return false;
 52         return true;
 53     }
 54 
 55     void init(int n)
 56     {
 57         this->n = n;
 58         for (int i = 0; i < n*2; i++) G[i].clear();
 59         memset(mark, 0, sizeof(mark));
 60     }
 61 
 62     /// x AND y = 1
 63     void add_and_one(int x,int y)
 64     {
 65         G[x^1].push_back(y);
 66         G[y^1].push_back(x);
 67         G[x].push_back(y);
 68         G[y^1].push_back(x^1);
 69         G[y].push_back(x);
 70         G[x^1].push_back(y^1);
 71     }
 72 
 73     /// x AND y = 0
 74     void add_and_zero(int x,int y)
 75     {
 76         G[x].push_back(y^1);
 77         G[y].push_back(x^1);
 78     }
 79 
 80     /// x OR y = 1
 81     void add_or_one(int x,int y)
 82     {
 83         G[x^1].push_back(y);
 84         G[y^1].push_back(x);
 85     }
 86 
 87     /// x OR y = 0
 88     void add_or_zero(int x,int y)
 89     {
 90         G[x].push_back(y^1);
 91         G[y].push_back(x^1);
 92         G[x].push_back(y);
 93         G[y^1].push_back(x^1);
 94         G[x^1].push_back(y^1);
 95         G[y].push_back(x);
 96     }
 97 
 98     /// x XOR y = 1
 99     void add_xor_one(int x,int y)
100     {
101         G[x^1].push_back(y);
102         G[y^1].push_back(x);
103         G[x].push_back(y^1);
104         G[y].push_back(x^1);
105     }
106 
107     /// x XOR y = 0
108     void add_xor_zero(int x,int y)
109     {
110         G[x^1].push_back(y^1);
111         G[y].push_back(x);
112         G[x].push_back(y);
113         G[y^1].push_back(x^1);
114     }
115 
116     /// x -> y
117     void add_to(int x,int y)
118     {
119         G[x].push_back(y);
120         G[y^1].push_back(x^1);
121     }
122 
123     bool solve()
124     {
125         for(int i = 0; i < n*2; i += 2)
126             if(!mark[i] && !mark[i+1])
127             {
128                 c = 0;
129                 if(!dfs(i))
130                 {
131                     while(c > 0) mark[S[--c]] = false;
132                     if(!dfs(i+1)) return false;
133                 }
134             }
135         return true;
136     }
137 } sat;
138 
139 int n;
140 struct Node
141 {
142     int x,y;
143 } node[maxn];
144 void init()
145 {
146     //
147 }
148 void input()
149 {
150     scanf("%d",&n);
151     for(int i=0; i<n; i++) scanf("%d%d",&node[i].x,&node[i].y);
152 }
153 bool test(int r)
154 {
155     sat.init(n);
156     for(int i=0; i<n; i++)
157     {
158         for(int j=i+1; j<n; j++)
159         {
160             if(abs(node[i].x-node[j].x)>=r||abs(node[i].y-node[j].y)>=2*r) continue;
161             if(abs(node[i].y-node[j].y)<r)
162             {
163                 if(node[i].y>node[j].y)
164                 {
165                     sat.G[2*i+1].push_back(2*i);
166                     sat.G[2*j].push_back(2*j+1);
167                 }
168                 else if(node[i].y<node[j].y)
169                 {
170                     sat.G[2*j+1].push_back(2*j);
171                     sat.G[2*i].push_back(2*i+1);
172                 }
173                 else
174                 {
175                     sat.add_xor_one(2*i,2*j);
176                 }
177             }
178             else
179             {
180                 if(node[i].y>node[j].y) sat.add_and_zero(2*i+1,2*j);
181                 else sat.add_and_zero(2*j+1,2*i);
182             }
183         }
184     }
185     if(sat.solve()) return 1;
186     return 0;
187 }
188 void solve()
189 {
190     int L=0,R=inf;
191     while(L<R)
192     {
193         int M=L+(R-L)/2;
194         if(!test(M)) R=M;
195         else L=M+1;
196     }
197     printf("%d\n",L-1);
198 }
199 void output()
200 {
201     //
202 }
203 int main()
204 {
205 //    std::ios_base::sync_with_stdio(false);
206 //    freopen("in.cpp","r",stdin);
207     int T;
208     scanf("%d",&T);
209     while(T--)
210     {
211         init();
212         input();
213         solve();
214         output();
215     }
216     return 0;
217 }
View Code

 

转载于:https://www.cnblogs.com/xysmlx/p/3404018.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值