现在的位置: 首页 > 综合 > 正文

POJ 3207 2-SAT

2013年08月03日 ⁄ 综合 ⁄ 共 1390字 ⁄ 字号 评论关闭

题意:给出一个圆,圆上有许多点,点与点之间有连线,连线要么在圆内,要么在圆外。现在给出所有连线的两个端点,判断这些线能否不相交?

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

const int SIZE = 5010;
int n, m;
int e[SIZE][2];

int head[SIZE], E;
bool instk[SIZE];
int stk[SIZE], top;
int blk[SIZE], blkCnt;
int low[SIZE], dfn[SIZE], tim;
struct EDGE { int v, next; } edge[SIZE*100];

void init()
{
    E = top = blkCnt = tim = 0;
    for(int i = 0; i < m + m; i++)
    {
        head[i] = blk[i] = low[i] = dfn[i] = -1;
        instk[i] = false;
    }
}

void add(int u, int v)
{
    edge[E].v = v;
    edge[E].next = head[u];
    head[u] = E++;
}

bool touch(int i, int j)
{
    if((e[i][0] <= e[j][0] && e[i][1] >= e[j][0] && e[i][1] <= e[j][1])
       || (e[i][0] >= e[j][0] && e[i][0] <= e[j][1] && e[i][1] >= e[j][1]))
        return true;
    return false;
}

void tarjan(int u)
{
    int v;
    instk[u] = true;
    stk[top++] = u;
    low[u] = dfn[u] = tim++;
    for(int i = head[u]; i != -1; i = edge[i].next)
    {
        v = edge[i].v;
        if(dfn[v] == -1)
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(instk[v])
            low[u] = min(low[u], dfn[v]);
    }

    if(low[u] == dfn[u])
    {
        if(top == -1 || top == 0) return;
        do
        {
            v = stk[top-1];
            top--;
            instk[v] = false;
            blk[v] = blkCnt;
        } while(v != u);
        blkCnt++;
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    int i, j;
    for(i = 0; i < m; i++)
    {
        scanf("%d%d",&e[i][0], &e[i][1]);
        if(e[i][0] > e[i][1]) swap(e[i][0], e[i][1]);
    }

    init();
    for(i = 0; i < m; i++)
        for(j = i + 1; j < m; j++)
            if(touch(i, j))
            {
                add(i, j+m);
                add(i+m, j);
                add(j, i+m);
                add(j+m, i);
            }

    for(i = 0; i < m + m; i++)
        if(dfn[i] == -1) tarjan(i);

    for(i = 0; i < m; i++)
        if(blk[i] == blk[i+m]) break;

    if(i == m) printf("panda is telling the truth...\n");
    else printf("the evil panda is lying again\n");
    return 0;
}
【上篇】
【下篇】

抱歉!评论已关闭.