寒假回老家那几天,看了蓝书的2-SAT专题介绍,觉得比较有趣。但天天串亲戚,没空刷题。开学后自己建了一个2-SAT专题训练,把经典问题都做了。觉得2-SAT难度不大,代码简单易懂。有些题构图比较有趣吧~~
2-SAT可行性的判断参照蓝书,简单易懂,自己写一遍就记住怎么写了~
我不建议学网上一些大牛的模板,太复杂了!!!比如kuangbin的2-SAT模板,写起来还是挺复杂的,我反正不会去看的。。
题目解析和代码实现我都放到GitHub上了 :2-SAT专题题解+AC代码
放一个截屏,看看成果吧~
为了方便大家想做题自己clone专题,我改成了public。 专题链接:点击打开链接
----------------------------------------------------------------------------------------------------------------------------
A:
难度不大,至于为啥错那么多。。是因为输出的字符串少打了一个字符。。。
这篇博客里有图帮助说明情况 点击打开链接
D:
题意:地图有N个城市,每个都要贴标签。
标签为正方形,而且标签的上边或下边的中点是城市,要求所有标签大小相等且不重叠。
求标签的最大边长。
分析: 求最大值二分答案。
每个城市只有在上边或下边两个状态,所以考虑构建2-SAT模型
如果两个城市横坐标之差的绝对值大于等于r,跳过
如果两个城市的纵坐标之差大于等于2r,跳过
如果两个城市纵坐标相等,只有一个贴上边,一个贴下边的情况
如果两个城市纵坐标之差绝对值小于r,则若上边的城市贴下面的标签就有矛盾,或者下边的城市贴上面的标签就会出现矛盾
如果两个城市纵坐标之差大于等于r,小于2r,则若上边城市贴下面的标签,下边城市贴上面的标签就会出现矛盾
F:
题意:三种逻辑运算,and,or,xor
给出N个变量,取值0或1
M个运算式子,问是否有解
分析:建图非常经典,加深了对2-SAT模型构建的理解
2-SAT模型中,每个有向边x->y表示 选了x必选y
AND运算:
若 c == 1, x->x' y->y' 所以是自我矛盾,不会出现x,y为0的情况
若 c == 0, x'->y y'->x 表示至少有一个为0
OR运算:跟AND十分类似,略
XOR运算:
若 c == 1, x->y' x'->y y->x' y'->x
若 c == 2, x->y y->x x'->y' y'->x'
然后就是跑一遍可行性判断
------------------------------------------------------------------------------------------------------------------------
其他印象没那么深刻,难度不大哈哈哈~
我还加了蓝书的两道例题(H,I),例题的话书上的解析很详细了,这里略
其他题目的详细解析都在GitHub上面,我就不全部贴出来了。 这里只把AC代码都贴出来~
-----------------------------------------------------------------------------------------------------------------------
POJ3207 - A题
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxm = 510;
const int maxn = 1010;
struct TwoSAT{
int n;
bool mark[maxn*2];
vector<int> G[maxn*2];
int S[maxn*2],c;
void init(int n){
this->n = n;
for (int i=0; i<n*2; i++) G[i].clear();
memset(mark,0,sizeof(mark));
}
inline void add(int x, int y) {G[x].push_back(y); }
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve(){
for (int i=0; i<2*n; i+=2) if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
return 1;
}
};
TwoSAT solver;
struct Point{
int x,y;
}p[maxm];
int n,m;
inline bool judge(int i, int j) {
return p[j].x>=p[i].x && p[j].x<=p[i].y && p[j].y>=p[i].y;
}
int main(){
while (scanf("%d%d",&n,&m)==2) {
solver.init(m);
for (int i=0; i<m; i++) {
scanf("%d%d",&p[i].x,&p[i].y);
if (p[i].x>p[i].y) swap(p[i].x,p[i].y);
}
for (int i=0; i<m; i++) {
for (int j=i+1; j<m; j++) {
if (judge(i,j) || judge(j,i)) {
solver.add(i*2,j*2+1);
solver.add(i*2+1,j*2);
solver.add(j*2,i*2+1);
solver.add(j*2+1,i*2);
}
}
}
if (solver.solve()) printf("panda is telling the truth...\n");
else printf("the evil panda is lying again\n");
}
return 0;
}
HDU1814 - B题
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 8000+5;
struct TwoSAT{
int n;
int S[maxn*2],c;
bool mark[maxn*2];
vector<int> G[maxn*2];
void init(int n) {
this->n = n;
for (int i=0; i<n*2; i++) G[i].clear();
memset(mark,0,sizeof(mark));
}
void add(int x, int y) {
G[x].push_back(y^1);
G[y].push_back(x^1);
}
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve() {
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n,m;
int main(){
while (scanf("%d%d",&n,&m)==2) {
solver.init(n);
int a,b;
for (int i=0; i<m; i++) {
scanf("%d%d",&a,&b);
a--; b--;
solver.add(a,b);
}
if (!solver.solve()) printf("NIE\n");
else {
for (int i=0; i<n; i++) if (solver.mark[i<<1]) printf("%d\n",i<<1|1);
else printf("%d\n",(i<<1)+2);
}
}
return 0;
}
HDU3622 - C题
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const double eps = 1e-8;
int dcmp(double x){
if (fabs(x)<eps) return 0;
return x<0?-1:1;
}
const int maxn = 100+5;
struct Point{
int x,y;
Point(int x=0, int y=0):x(x),y(y){}
};
Point p1[maxn],p2[maxn];
int n;
struct TwoSAT{
int S[maxn<<1],c;
bool mark[maxn<<1];
vector<int> G[maxn<<1];
int n;
void init(int n) {
this->n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<n*2; i++) G[i].clear();
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval;
y = y*2 + yval;
G[y^1].push_back(x);
G[x^1].push_back(y);
}
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve() {
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
double dis1[maxn][maxn][2];
double dis2[maxn][maxn][2];
inline double Length(Point a, Point b) {
return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );
}
bool judge(double mid) {
mid = mid*2;
solver.init(n);
for (int i=0; i<n; i++) {
for (int j=i+1; j<n; j++) {
if ( dcmp(dis1[i][j][0]-mid)<0 ) solver.add(i,0,j,0);
if ( dcmp(dis2[i][j][0]-mid)<0 ) solver.add(i,1,j,0);
if ( dcmp(dis1[i][j][1]-mid)<0 ) solver.add(i,0,j,1);
if ( dcmp(dis2[i][j][1]-mid)<0 ) solver.add(i,1,j,1);
}
}
return solver.solve();
}
int main(){
while (scanf("%d",&n)==1) {
int x,y;
for (int i=0; i<n; i++) {
scanf("%d%d",&x,&y); p1[i] = Point(x,y);
scanf("%d%d",&x,&y); p2[i] = Point(x,y);
}
for (int i=0; i<n; i++) {
for (int j=i+1; j<n; j++) dis1[i][j][0] = Length(p1[i],p1[j]), dis1[i][j][1] = Length(p1[i],p2[j]);
for (int j=i+1; j<n; j++) dis2[i][j][0] = Length(p2[i],p1[j]), dis2[i][j][1] = Length(p2[i],p2[j]);
}
double left = 0, right = 1e5;
double mid, ans = 0;
while (right-left>eps) {
mid = (left+right)*0.5;
if (judge(mid)) {
ans = mid;
left = mid+eps;
}
else right = mid-eps;
}
printf("%.2f\n",ans);
}
return 0;
}
POJ2296 - D题
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 100+5;
struct TwoSAT{
int S[maxn*2],c;
bool mark[maxn*2];
vector<int> G[maxn*2];
int n;
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
void init(int n) {
this->n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<n*2; i++) G[i].clear();
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval;
y = y*2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool solve() {
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i^1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n;
struct Point{
int x,y;
}p[maxn];
bool judge(int r) {
solver.init(n);
int up,down;
for (int i=0; i<n; i++) {
for (int j=0; j<i; j++) if (abs(p[i].x-p[j].x)<r){
if (p[i].y > p[j].y) up = i, down = j;
else up = j, down = i;
if (p[up].y == p[down].y) {
solver.add(up,0,down,0);
solver.add(up,1,down,1);
continue;
}
if (p[up].y - p[down].y < 2*r) {
if (p[up].y - p[down].y < r) {
solver.add(up,0,up,0);
solver.add(down,1,down,1);
}
else {
solver.add(up,0,down,1);
}
}
}
}
return solver.solve();
}
int main(){
int T;
scanf("%d",&T);
while (T--) {
scanf("%d",&n);
for (int i=0; i<n; i++) scanf("%d%d",&p[i].x,&p[i].y);
int left = 0, right = 10000;
int mid , ans = 0;
while (left<=right) {
mid = (left+right)>>1;
if (judge(mid)) left = mid+1, ans = mid;
else right = mid-1;
}
printf("%d\n",ans);
}
return 0;
}
POJ3648 - E题
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 100+5;
struct TwoSAT{
int n;
int S[maxn*2],c;
bool mark[maxn*2];
vector<int> G[maxn*2];
void init(int n) {
this->n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<n*2; i++) G[i].clear();
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval; y = y*2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++) if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve(){
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n,m;
int a1,a2;
int v1,v2;
char c1,c2;
int main(){
while (scanf("%d%d",&n,&m)==2) {
solver.init(n);
while (m--) {
scanf("%d%c%d%c",&a1,&c1,&a2,&c2);
if (c1 == 'h') v1 = 0; else v1 = 1;
if (c2 == 'h') v2 = 0; else v2 = 1;
solver.add(a1,v1,a2,v2);
}
solver.add(0,1,0,1);
if (!solver.solve()) printf("bad luck\n");
else {
for (int i=2; i<n*2; i+=2) {
if (solver.mark[i]) printf("%dh ",i/2);
else printf("%dw ",i/2);
}
printf("\n");
}
}
return 0;
}
POJ3678 - F题
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 1000+5;
struct TwoSAT{
int n;
int S[maxn*2],c;
bool mark[maxn*2];
vector<int> G[maxn*2];
void init(int n) {
this-> n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<n*2; i++) G[i].clear();
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval;
y = y*2 + yval;
G[x].push_back(y);
}
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve() {
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n,m;
int a,b,c;
char s[5];
int main(){
while (scanf("%d%d",&n,&m)==2) {
solver.init(n);
while (m--) {
scanf("%d%d%d%s",&a,&b,&c,s);
if (s[0]=='A') {
if (c == 1) solver.add(a,0,a,1),solver.add(b,0,b,1);
else solver.add(a,1,b,0),solver.add(b,1,a,0);
}
else if (s[0]=='O') {
if (c == 1) solver.add(a,0,b,1),solver.add(b,0,a,1);
else solver.add(a,1,a,0),solver.add(b,1,b,0);
}
else {
if (c == 1) solver.add(a,1,b,0),solver.add(a,0,b,1),solver.add(b,1,a,0),solver.add(b,0,a,1);
else solver.add(a,0,b,0),solver.add(a,1,b,1),solver.add(b,0,a,0),solver.add(b,1,a,1);
}
}
if (solver.solve()) printf("YES\n"); else printf("NO\n");
}
return 0;
}
HDU4115 - G题
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 10000+5;
struct TwoSAT{
int n;
bool mark[maxn*2];
int S[maxn*2],c;
vector<int> G[maxn*2];
void init(int n) {
this->n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<n*2; i++) G[i].clear();
}
void add(int x, int xval , int y, int yval) {
x = x*2 + xval; y = y*2 + yval;
G[x].push_back(y);
}
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve(){
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n,m;
int a[maxn],b[maxn];
int x,y,z;
int main(){
int T;
scanf("%d",&T);
for (int kase = 1; kase <= T; kase++) {
scanf("%d%d",&n,&m);
for (int i=0; i<n; i++) {
scanf("%d",&a[i]);
if (a[i]==1) b[i] = 2;
else if (a[i]==2) b[i] = 3;
else b[i] = 1;
if (a[i]>b[i]) swap(a[i],b[i]);
}
solver.init(n);
while (m--) {
scanf("%d%d%d",&x,&y,&z);
x--; y--;
if (z == 0) {
if (a[x]!=a[y]) {
solver.add(x,0,y,1);
solver.add(y,0,x,1);
}
if (a[x]!=b[y]) {
solver.add(x,0,y,0);
solver.add(y,1,x,1);
}
if (b[x]!=b[y]) {
solver.add(x,1,y,0);
solver.add(y,1,x,0);
}
if (b[x]!=a[y]) {
solver.add(x,1,y,1);
solver.add(y,0,x,0);
}
}
else {
if (a[x]==a[y]) {
solver.add(x,0,y,1);
solver.add(y,0,x,1);
}
if (a[x]==b[y]) {
solver.add(x,0,y,0);
solver.add(y,1,x,1);
}
if (b[x]==b[y]) {
solver.add(x,1,y,0);
solver.add(y,1,x,0);
}
if (b[x]==a[y]) {
solver.add(x,1,y,1);
solver.add(y,0,x,0);
}
}
}
if (solver.solve()) printf("Case #%d: yes\n",kase);
else printf("Case #%d: no\n",kase);
}
return 0;
}
UVALive3211 - H题
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 2000+5;
struct TwoSAT {
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2],c;
void init(int n){
this->n = n;
for (int i=0; i<n*2; i++) G[i].clear();
memset(mark,0,sizeof(mark));
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval;
y = y*2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool dfs(int x){
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve() {
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n;
int T[maxn][2];
inline int Max(int x, int y) {return x>y?x:y; }
bool judge(int mid) {
solver.init(n);
for (int i=0; i<n; i++)
for (int a=0; a<2; a++)
for (int j=i+1; j<n; j++)
for (int b=0; b<2; b++)
if (abs(T[i][a]-T[j][b])<mid) solver.add(i,a^1,j,b^1);
return solver.solve();
}
int main(){
while (scanf("%d",&n)==1 && n){
int left = 0, right = 0;
for (int i=0; i<n; i++) {
for (int j=0; j<2; j++) {
scanf("%d",&T[i][j]);
right = Max(right,T[i][j]);
}
}
int mid,ans;
while (left<=right) {
mid = (left+right)>>1;
if (judge(mid)) {
ans = mid;
left = mid+1;
}
else right = mid-1;
}
printf("%d\n",ans);
}
return 0;
}
UVALive3713 - I题
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 100000+5;
struct TwoSAT{
int n;
int S[maxn*2],c;
bool mark[maxn*2];
vector<int> G[maxn*2];
void init(int n){
this->n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<2*n; i++) G[i].clear();
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval;
y = y*2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool dfs(int x){
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve(){
for (int i=0; i<2*n; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n,m;
int total_age;
int age[maxn];
inline bool is_young(int x) { return age[x]*n<total_age; }
int main(){
while (scanf("%d%d",&n,&m)==2 && n+m) {
total_age = 0;
for (int i=0; i<n; i++) scanf("%d",&age[i]), total_age += age[i];
solver.init(n);
int a,b;
for (int i=0; i<m; i++) {
scanf("%d%d",&a,&b);
a--; b--;
if (a==b) continue;
solver.add(a,1,b,1);
if (is_young(a) == is_young(b)) solver.add(a,0,b,0);
}
if (!solver.solve()) printf("No solution.\n");
else {
for (int i=0; i<n; i++)
if (solver.mark[i*2]) printf("C\n");
else if (age[i]*n<total_age) printf("B\n");
else printf("A\n");
}
}
return 0;
}
ZOJ3656 - J题
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn = 500+5;
struct TwoSAT{
int n;
bool mark[maxn*2];
int S[maxn*2],c;
vector<int> G[maxn*2];
void init(int n) {
this->n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<n*2; i++) G[i].clear();
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval; y = y*2 + yval;
G[x].push_back(y);
}
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve() {
for (int i=0; i<n*2; i+=2) {
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
}
return 1;
}
};
TwoSAT solver;
int n;
int mat[maxn][maxn];
inline bool judge(){
for (int i=0; i<n; i++) {
if (mat[i][i]!=0) return 0;
for (int j=i+1; j<n; j++) if (mat[i][j] != mat[j][i]) return 0;
}
return 1;
}
int main(){
while (scanf("%d",&n)==1) {
for (int i=0; i<n; i++)
for (int j=0; j<n; j++) scanf("%d",&mat[i][j]);
if (!judge()) {
printf("NO\n");
continue;
}
bool flag = 1;
for (int k=0; k<31; k++) {
solver.init(n);
for (int i=0; i<n; i++) {
for (int j=i+1; j<n; j++) {
if (i%2==1 && j%2==1) {
if (mat[i][j]&1) {
solver.add(i,0,j,1);
solver.add(j,0,i,1);
}
else {
solver.add(i,1,i,0);
solver.add(j,1,j,0);
}
}
else if (i%2==0 && j%2==0) {
if (mat[i][j]&1) {
solver.add(i,0,i,1);
solver.add(j,0,j,1);
}
else {
solver.add(i,1,j,0);
solver.add(j,1,i,0);
}
}
else {
if (mat[i][j]&1) {
solver.add(i,0,j,1);
solver.add(i,1,j,0);
solver.add(j,0,i,1);
solver.add(j,1,i,0);
}
else {
solver.add(i,0,j,0);
solver.add(i,1,j,1);
solver.add(j,0,i,0);
solver.add(j,1,i,1);
}
}
mat[i][j]>>=1;
}
}
flag = solver.solve();
if (flag == 0) break;
}
if (!flag) printf("NO\n"); else printf("YES\n");
}
return 0;
}
HDU1815 - K题
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int INF = 1e7;
const int maxn = 510;
const int maxm = 1000+10;
struct TwoSAT{
int n;
int S[maxn*2],c;
bool mark[maxn*2];
vector<int> G[maxn*2];
void init(int n) {
this->n = n;
memset(mark,0,sizeof(mark));
for (int i=0; i<n*2; i++) G[i].clear();
}
void add(int x, int xval, int y, int yval) {
x = x*2 + xval;
y = y*2 + yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
bool dfs(int x) {
if (mark[x^1]) return 0;
if (mark[x]) return 1;
mark[x] = 1;
S[c++] = x;
for (int i=0; i<G[x].size(); i++)
if (!dfs(G[x][i])) return 0;
return 1;
}
bool solve() {
for (int i=0; i<n*2; i+=2)
if (!mark[i] && !mark[i+1]) {
c = 0;
if (!dfs(i)) {
while (c>0) mark[S[--c]] = 0;
if (!dfs(i+1)) return 0;
}
}
return 1;
}
}solver;
int n,A,B;
struct Point {
int x,y;
};
Point s1,s2;
Point p[maxn];
struct Edge{
int u,v;
Edge (int u=0, int v=0): u(u), v(v) {}
};
Edge hate[maxm],like[maxm];
int d1[maxn],d2[maxn],Len;
inline int Length(Point a, Point b) {
return abs(a.x-b.x) + abs(a.y-b.y);
}
void build(int mid){
for (int i=0; i<A; i++) solver.add(hate[i].u,0,hate[i].v,0), solver.add(hate[i].u,1,hate[i].v,1);
for (int i=0; i<B; i++) solver.add(like[i].u,1,like[i].v,0), solver.add(like[i].u,0,like[i].v,1);
for (int i=0; i<n; i++) {
for (int j=i+1; j<n; j++) {
if (d1[i]+d1[j]>mid) solver.G[i*2].push_back(j*2+1), solver.G[j*2].push_back(i*2+1);
if (d2[i]+d2[j]>mid) solver.G[i*2+1].push_back(j*2), solver.G[j*2+1].push_back(i*2);
if (d1[i]+Len+d2[j]>mid) solver.G[i*2].push_back(j*2), solver.G[j*2+1].push_back(i*2+1);
if (d2[i]+Len+d1[j]>mid) solver.G[i*2+1].push_back(j*2+1), solver.G[j*2].push_back(i*2);
}
}
}
int main(){
while (scanf("%d%d%d",&n,&A,&B)==3) {
scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y);
Len = Length(s1,s2);
for (int i=0; i<n; i++) scanf("%d%d",&p[i].x,&p[i].y);
for (int i=0; i<n; i++) d1[i] = Length(p[i],s1), d2[i] = Length(p[i],s2);
int u,v;
for (int i=0; i<A; i++) {
scanf("%d%d",&u,&v);
u--; v--;
hate[i] = Edge(u,v);
}
for (int i=0; i<B; i++) {
scanf("%d%d",&u,&v);
u--; v--;
like[i] = Edge(u,v);
}
int left = 0, right = INF;
int mid, ans = -1;
while (left<=right) {
mid = (left+right)>>1;
solver.init(n);
build(mid);
if (solver.solve()) {right = mid-1; ans = mid;}
else left = mid+1;
}
printf("%d\n",ans);
}
return 0;
}