[Problem Description]
![](http://www.lydsy.com/JudgeOnline/images/1997_1.jpg)
[Algorithm]
2-sat
[Analysis]
这道题看起来似乎毫无头绪,但仔细想想就能发现其中的奥妙。由于图中有一个哈密顿回路,要想构成平面图就需要先按照这个顺序把点排成一圈。每一条边加进去的时候有两种方法,第一种是从环内连,第二种是从环外连,两种方法选其一。这不就是2-sat问题的模型嘛!而交叉的两条边不能同时出现,根据这个建图然后用o(n)方法判断是否可行即可。这里还有一个问题,由于边数很大,直接做的话会TLE & MLE。但是平面图有一个性质,平面图最多边数为 V * 3 - 6,以此先判断一下再做就不用担心TLE & MLE 了。
[Code]
/**************************************************************
Problem: 1823
User: gaotianyu1350
Language: C++
Result: Accepted
Time:40 ms
Memory:1700 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <iostream>
using namespace std;
#define MAXN 2000
#define MAXM 50000
int point[MAXN], next[MAXM], v[MAXM];
int dfsTime[MAXN], lessTime[MAXN], cct[MAXN], st[MAXN];
int nowTime, cntCct, top, tot;
int n, m;
inline void clear()
{
memset(point, 0, sizeof(point));
memset(next, 0, sizeof(next));
memset(v, 0, sizeof(v));
memset(dfsTime, 0, sizeof(dfsTime));
memset(lessTime, 0, sizeof(lessTime));
memset(cct, 0, sizeof(cct));
memset(st, 0, sizeof(st));
nowTime = 0;
cntCct = 0;
top = 0;
tot = 0;
}
inline int min(int a, int b)
{
return a < b ? a : b;
}
inline int max(int a, int b)
{
return a > b ? a : b;
}
void tarjan(int now)
{
lessTime[now] = dfsTime[now] = ++nowTime;
st[++top] = now;
for (int temp = point[now]; temp; temp = next[temp])
{
int tar = v[temp];
if (!dfsTime[tar])
{
tarjan(tar);
lessTime[now] = min(lessTime[now], lessTime[tar]);
}
else
if (!cct[tar])
lessTime[now] = min(lessTime[now], dfsTime[tar]);
}
if (lessTime[now] == dfsTime[now])
{
cntCct++;
while (1)
{
cct[st[top--]] = cntCct;
if (st[top + 1] == now) break;
}
}
}
inline void addedge(int x, int y)
{
tot++;
next[tot] = point[x], point[x] = tot, v[tot] = y;
}
inline int part(int x)
{
return ((x - 1) ^ 1) + 1;
}
int main()
{
//freopen("input.txt", "r", stdin);
int testcase;
cin >> testcase;
while (testcase--)
{
scanf("%d%d", &n, &m);
clear();
for (int i = 1; i <= m; i++)
{
char x1, x2;
int y1, y2;
scanf(" %c%d %c%d", &x1, &y1, &x2, &y2);
int x = y1 * 2 - (x1 == 'm' ? 1 : 0);
int y = y2 * 2 - (x2 == 'm' ? 1 : 0);
addedge(part(x), y);
addedge(part(y), x);
}
for (int i = 1; i <= 2 * n; i++)
if (!dfsTime[i])
tarjan(i);
bool isok = true;
for (int i = 1; i <= n; i++)
if (cct[i * 2 - 1] == cct[i * 2])
isok = false;
if (isok)
printf("GOOD\n");
else
printf("BAD\n");
}
}