条件转化，2-sat BZOJ 1997

http://www.lydsy.com/JudgeOnline/problem.php?id=1997

1997: [Hnoi2010]Planar

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1810  Solved: 684
[Submit][Status][Discuss]

2
6 9
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
1 4 2 5 3 6
5 5
1 2
2 3
3 4
4 5
5 1
1 2 3 4 5

Sample Output

NO
YES

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 1e5 + 5;
struct TwoSat{
int n, c, s[maxn * 2];
bool mark[maxn << 1];
vector<int> G[maxn << 1];

void init(int n){
this->n = n;
for (int i = 0; i < 2 * n; i++) G[i].clear();
memset(mark, false, sizeof(mark));
}

void add_edge(int x, int xval, int y, int yval){
x = x * 2 + xval, y = y * 2 + yval;
G[x ^ 1].pb(y), G[y ^ 1].pb(x);
}

void display(){
for (int i = 0; i < 2 * n; i++){
printf("from = %d\n", i);
for (int j = 0; j < G[i].size(); j++){
printf("%d ", G[i][j]);
}
cout << endl;
}
}

bool dfs(int x){
if (mark[x ^ 1]) return false;
if (mark[x]) return true;
mark[x] = true;
s[c++] = x;
for (int i = 0; i < G[x].size(); i++){
if (!dfs(G[x][i])) return false;
}
return true;
}

bool solve(){
for (int i = 0; i < n * 2; i += 2){
if (!mark[i] && !mark[i + 1]){
c = 0;
if (!dfs(i)){
while (c) mark[s[--c]] = false;
if (!dfs(i + 1)) return false;
}
}
}
return true;
}

};
TwoSat tar;
int n, m;
map<int, int> id;
map<pair<int, int>, int> Point;
vector<pair<int, int> > edges;

bool test(int u1, int v1, int u2, int v2){
if (u2 > u1 && u2 < v1 && v2 > v1) return true;
if (u1 > u2 && u1 < v2 && v1 > v2) return true;
return false;
}

int main(){
int T; cin >> T;
while (T--){
scanf("%d%d", &n, &m);
id.clear();
edges.clear();
for (int i = 0; i < m; i++){
int u, v; scanf("%d%d", &u, &v);
if (u > v) swap(u, v);
edges.push_back(mk(u, v));
}
for (int i = 1; i <= n; i++){
int u; scanf("%d", &u);
id[u] = i;
}
if (m >= n * 3 + 6){
puts("NO"); continue;
}
tar.init(m);
for (int i = 0; i < m; i++){
int x1 = edges[i].fi, y1 = edges[i].se;
x1 = id[x1], y1 = id[y1];
if (x1 > y1) swap(x1, y1);

for (int j = i + 1; j < m; j++){
int x2 = edges[j].fi, y2 = edges[j].se;
x2 = id[x2], y2 = id[y2];
if (x2 > y2) swap(x2, y2);
//if (x1 == x2 || x1 == y2 || y1 == x2 || y1 == y2) continue;
if (test(x1, y1, x2, y2)){///假定刚开始都是在里面的
}
}
}
//tar.display();
if (tar.solve()) puts("YES");
else puts("NO");
}
return 0;
}
View Code

posted @ 2017-03-19 22:06  知る奇迹に  阅读(221)  评论(0编辑  收藏  举报