zoukankan      html  css  js  c++  java
  • POJ3207(2SAT)

    View Code
    /*2-sat问题
    2-SAT问题,通俗的说就是有n对点(2n个点),从每对点中选出一个点,共选出n个点,
    而且要满足若干个这样的条件:某两点不能同时被选出。
    设一对点为x、~x,如果a被选出则b一定要被选出,就在图中加有向弧(a,b)表示这种关系。
    那么如果a,b(a!=b,a!=~b)不能同时被选出,那么加两条有向弧(a,~b),(b,~a)。
    这样由图的对称性可以证明,2-SAT有解等价于任取x、~x,x、~x不在一个强联通分量中。
    题意就是:平面上,一个圆,圆的边上按顺时针放着n个点。现在要连m条边,比如a,b,
    那么a到b可以从圆的内部连接,也可以从圆的外部连接。给你的信息中,每个点最多只会连接的一条边。
    问能不能连接这m条边,使这些边都不相交。
    1:每个边看成2个点:分别表示在内部连接和在外部连接,只能选择一个。计作点i和点i'
    2:如果两条边i和j必须一个画在内部,一个画在外部(一个简单判断就可以)
    那么连边:
    i->j’, 表示i画内部的话,j只能画外部,即j’
    j->i’,同理
    i’->j,同理
    j’->i,同理
    然后就是2-sat算法了,tarjan一下,如果有i和i'同属于一个强联通,返回false,否则就成立
    
    Problem: 3207  User: HEU_daoguang
    Memory: 2860K  Time: 63MS
    Language: G++  Result: Accepted
    */
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    #define E 1000500
    #define V 2005
    int top,cnt,index,n,m,ecnt;
    bool instack[V];
    int stack[V],id[V],dfn[V],low[V],in[V],link[E][2];
    int head[V];
    struct edge{
        int s,t,next;
    }e[E];
    void addedge(int u,int v){
        e[ecnt].s=u;
        e[ecnt].t=v;
        e[ecnt].next=head[u];
        head[u]=ecnt++;
    }
    void tarjan(int u){
        int v;
        int tmp;
        dfn[u]=low[u]=++index;
        instack[u]=true;
        stack[++top]=u;
        for(int k=head[u];k!=-1;k=e[k].next){
            v=e[k].t;
            if(!dfn[v]){
                tarjan(v);
                if(low[v]<low[u])
                    low[u]=low[v];
            }
            else if(instack[v] && dfn[v]<low[u]){
                low[u]=dfn[v];
            }
        }
        if(dfn[u]==low[u]){
            cnt++;
            do{
                tmp=stack[top--];
                instack[tmp]=false;
                id[tmp]=cnt;
            }
            while(tmp!=u);
        }
    }
    void build(){
        memset(head,-1,sizeof(head));
            ecnt=0;
            for(int i=0;i<m;i++)
                for(int j=i+1;j<m;j++){
                    if(link[i][0] < link[j][1] && link[i][0] > link[j][0] && link[i][1] > link[j][1]
                    || link[i][1] < link[j][1] && link[i][1] > link[j][0] && link[i][0] < link[j][0])
                    {
                        addedge(i,j+m);
                        addedge(j,i+m);
                        addedge(j+m,i);
                        addedge(i+m,j);
                    }
                }
    }
    void solve(){
        top=cnt=index=0;
        memset(dfn,0,sizeof(dfn));
        for(int i=0;i<2*m;i++)
            if(!dfn[i])
                tarjan(i);
    }
    void judge(){
        bool flag=true;
        for(int i=0;i<m;i++)
        {
            if(id[i]==id[i+m])
            {
                flag=false;
                break;
            }
        }
        if(flag) printf("panda is telling the truth...\n");
        else printf("the evil panda is lying again\n");
    }
    int main()
    {
        while(cin >> n >> m){
            for(int i=0;i<m;i++){
                cin >> link[i][0] >> link[i][1];
                if(link[i][0]>link[i][1]) swap(link[i][0],link[i][1]);
            }
            build();
            solve();
            judge();
        }
        return 0;
    }

    第一道2-SAT,今天一定要A第二道,加油。

    2-SAT膜拜7道题:http://hi.baidu.com/liveroom/blog/category/2-sat

  • 相关阅读:
    组合,多态,封装
    继承and派生
    面向对象编程 类 后补充了元类 和单例
    数据结构与算法(Python)
    git版本控制系统命令
    python数据类型
    MVC与MTV模型及Django请求的生命周期
    linux目录文件及系统启动知识
    linux命令汇总
    Python字符串和列表的内置方法
  • 原文地址:https://www.cnblogs.com/markliu/p/2601624.html
Copyright © 2011-2022 走看看