[BZOJ1997][HNOI2010][2-sat]Planar

来源:互联网 发布:网络电视港澳台的apk 编辑:程序博客网 时间:2024/05/19 17:56
[Problem Description]

[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");    }}


0 0
原创粉丝点击