POJ 3207 Ikki's Story IV - Panda's Trick(2-SAT判断)

【题目链接】

http://poj.org/problem?id=3207


【题目大意】

一个圆圈上有N个数:0,1,2……N-1。 然后有m条线两两连接这些点,这些线可以在圆圈里面,也可以在圆圈外面。问有没有一种方式,使得这些线都不相交。



【思路】

以线为单位,每条线要么在圆圈里面,要么在圆圈外面,典型的2-SAT模型。


【代码】

#include<iostream> 
#include<cstdio>
#include<cstring>
using namespace std;

typedef long long int64;

const int MAXN = 1010;
const int VN   = MAXN*2;
const int EN   = VN*VN/2;
int n, m;
int arr[VN][2];

struct Graph{
    int size;
    int head[VN];
    struct{
        int v, next;
    }E[EN];

    void init(){
        size = 0;
        memset(head, -1, sizeof(head));
    }
    void addEdge(int u, int v){
        E[size].v = v;
        E[size].next = head[u];
        head[u] = size++;
    }
}g;

class Two_Sat{
public:
    bool check(const Graph& g, const int n){
        scc(g, n);
        for(int i=0; i<n; ++i)
            if(belong[i] == belong[i+n]) 
                return false;
        return true;
    }
private:
    void tarjan(const Graph& g, const int u){
        int v;
        DFN[u] = low[u] = ++idx;
        sta[top++] = u;
        instack[u] = true;

        for(int e=g.head[u]; e!=-1; e=g.E[e].next){
            v = g.E[e].v;
            if(DFN[v] == -1){
                tarjan(g, v);
                low[u] = min(low[u], low[v]);
            }else if(instack[v]){
                low[u] = min(low[u], DFN[v]);
            }
        }

        if(DFN[u] == low[u]){
            ++bcnt;
            do{
                v = sta[--top];
                instack[v] = false;
                belong[v] = bcnt;
            }while(u != v);
        }
    }

    void scc(const Graph& g, const int n){
        idx = top = bcnt = 0;
        memset(DFN, -1, sizeof(DFN));
        memset(instack, 0, sizeof(instack));
        for(int i=0; i<2*n; ++i)
            if(DFN[i] == -1)
                tarjan(g, i);
    }
private:
    int idx, top, bcnt;
    int DFN[VN];
    int low[VN];
    int sta[VN];
    int belong[VN];
    bool instack[VN];

}sat;


bool isCross(int* A, int *B){
    return  A[0]>B[0]&&A[0]<B[1] && (A[1]<B[0] || A[1]>B[1])
         || A[1]>B[0]&&A[1]<B[1] && (A[0]<B[0] || A[0]>B[1]);
}

int main(){
    while(~scanf("%d%d", &n, &m)){
    
        g.init();
        for(int i=0; i<n; ++i){
            scanf("%d%d", &arr[i][0], &arr[i][1]);
            if(arr[i][0] > arr[i][1]) swap(arr[i][0], arr[i][1]);
        }

        for(int i=0; i<n; ++i){
            for(int j=i+1; j<n; ++j){
                if(isCross(arr[i], arr[j])) {
                    g.addEdge(i, j+n);
                    g.addEdge(i+n, j);
                    g.addEdge(j, i+n);
                    g.addEdge(j+n, i);
                }
            }
        }
        if(sat.check(g, n)) puts("panda is telling the truth...");
        else puts("the evil panda is lying again");

    }   
    return 0;
}





你可能感兴趣的:(poj)