POJ 3207 Ikki's Story IV

2-SAT,判断任意两条线段是否内部互斥或者外部互斥就可以建图了。

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

const int maxn=8000+5;
int M,N;
int L[maxn],R[maxn];

struct TwoSAT
{
    int n;
    vector<int> G[maxn*2];
    bool mark[maxn*2];
    int S[maxn*2],c;

    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;
    }

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

    void add_clause(int x,int y)
    {
        G[x].push_back(y^1);
        G[y].push_back(x^1);
    }

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

bool pan(int x,int l,int r)
{
    if(l<x&&x<r) return 1;
    else return 0;
}

int main()
{
    while(~scanf("%d%d",&M,&N))
    {
        TwoSAT T; T.init(N);
        for(int i=0;i<N;i++)
        {
            scanf("%d%d",&L[i],&R[i]);
            if(L[i]>R[i]) swap(L[i],R[i]);
        }
        for(int i=0;i<N;i++)
        {
            int Le=L[i],Ri=R[i];
            for(int j=i+1;j<N;j++)
            {
                if(pan(L[j],Le,Ri)==1&&pan(R[j],Le,Ri)==0)
                {
                    T.add_clause(2*i,2*j);//放内部互斥
                    T.add_clause(2*j+1,2*i+1);//放外部互斥
                }
                else if(pan(L[j],Le,Ri)==0&&pan(R[j],Le,Ri)==1)
                {
                    T.add_clause(2*i,2*j);//放内部互斥
                    T.add_clause(2*j+1,2*i+1);//放外部互斥
                }
            }
        }
        if(T.solve()) printf("panda is telling the truth...
");
        else printf("the evil panda is lying again
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/4906459.html