zoukankan      html  css  js  c++  java
  • poj 3207 2-SAT问题

    思路:将线段按开始点的升序排序,对线段尾节点进行判断,若存在交叉,那么这两条线段就不能同时在内或同时在外。这样将每条线段在内和在外看成两个状态ii',i表示线段在内,i'表示线段在外。假使线段i和线段j相交,那么ij是矛盾,且i'j'是矛盾。

    具体见代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define Maxn 2010
    #define Maxm Maxn*Maxn
    using namespace std;
    int vi[Maxn],head[Maxn],dfn[Maxn],low[Maxn],e,n,lab,top,num,m,id[Maxn],Stack[Maxn];
    struct Edge{
        int u,v,next;
    }edge[Maxm];
    struct line{
        int u,v;
    }p[Maxn];
    void init()//初始化
    {
        memset(vi,0,sizeof(vi));
        memset(head,-1,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(id,0,sizeof(id));
        e=lab=top=num=0;
    }
    void add(int u,int v)//加边
    {
        edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
    }
    int cmp(line a,line b)
    {
        if(a.u==b.u)
            return a.v<b.v;
        return a.u<b.u;
    }
    void Tarjan(int u)//找出强连通分支
    {
        int i,j,v;
        //cout<<u<<endl;
        dfn[u]=low[u]=++lab;
        Stack[top++]=u;
        vi[u]=1;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            if(vi[v])
            low[u]=min(low[u],dfn[v]);
    
        }
        if(low[u]==dfn[u])
        {
            ++num;
            do{
                i=Stack[--top];
                vi[i]=0;
                id[i]=num;
            }while(i!=u);
        }
    }
    int solve()
    {
        int i,j;
        for(i=1;i<=m*2;i++)
            if(!dfn[i])
            Tarjan(i);
        for(i=1;i<=m;i++)
            if(id[i]==id[i+m])
                return 0;//有矛盾则结束
        return 1;
    }
    int cross(line a,line b)
    {
        if(a.v>b.u&&a.v<b.v)
            return 1;
        return 0;
    }
    int main()
    {
        int i,j,a,b;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            init();
            for(i=1;i<=m;i++)
            {
                scanf("%d%d",&a,&b);
                p[i].u=a<b?a:b;
                p[i].v=a>b?a:b;
            }
            sort(p+1,p+1+m,cmp);
            for(i=1;i<m;i++)
            for(j=i+1;j<=m;j++)
            {
                if(cross(p[i],p[j]))//如果有两条线的区间相交,那么存在矛盾
                {
                    add(i,j+m);
                    add(j,i+m);
                    add(i+m,j);
                    add(j+m,i);
                }
            }
            if(solve())
                printf("panda is telling the truth...
    ");
            else
                printf("the evil panda is lying again
    ");
        }
        return 0;
    }
  • 相关阅读:
    计算机与软件工程 作业一
    软件工程作业6 咸鱼不闲团队 校园二手交易系统
    软件工程 作业5
    计算与软件工程 作业4
    软件工程第四次作业评价总结
    计算与软件工程 作业3
    计算与软件共程作业2
    计算与软件工程 作业一
    计算与软件工程作业六
    计算与软件工程作业五
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3221170.html
Copyright © 2011-2022 走看看