zoukankan      html  css  js  c++  java
  • POJ3207 Ikki's Story IV

    开始学习2-sat的姿势

    http://blog.csdn.net/jarjingx/article/details/8521690

    这篇文章写的真好

    算法的过程如下:
    构图
      更具体的后面再说
    缩点
      Tarjan算法缩点,将所有的边反过来( 为什么?后面有嗯 )
    判可行
      枚举集合的两个元素,看其是否处于不同的块内,若否的话则给出不可行信息
    记录矛盾
      这里所说的矛盾不是题中给出的两个人之间有仇恨,那样的边是实际存在,我们这里说的矛盾是指若两个块分别含有两个对立节点,也就是说一个集合的两个元素分布在了两个不同的块中,那么这两个块就是矛盾的,即不可能同时被选择,这样一种矛盾关系是不存在于边中的,是不依赖于输入的数据的,我们要找到与一个块对立的块,并把它们保存下来。
    拓扑排序
      将缩点后的图进行拓扑排序(排的是块而不是节点)
    构造方案
      按照拓扑序列的顺序,依次访问所有块,若一个块未被标记,将其标记为“选择”,不传递“选择”标记,将被选块的对立块标记为“不选择”,将其“不选择”标记沿着边正向传递。( 不是逆着边么?哼,图已经被反过来了,你到底有没有认真看呐!囧 )

    本题建图判断即可

    By:大奕哥

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+5;
    int low[N],vis[N],dfn[N],n,m,cnt,ccnt,num,head[N],s[N],top,col[N];
    struct node{
        int x,y;
    }p[N];
    struct edge
    {
        int to,nex;
    }e[N<<2];
    void add(int x,int y)
    {
        e[++ccnt].to=y;e[ccnt].nex=head[x];head[x]=ccnt;
    }
    void dfs(int x)
    {
        s[++top]=x;
        vis[x]=1;dfn[x]=low[x]=++cnt;
        for(int i=head[x];i;i=e[i].nex)
        {
            int y=e[i].to;
            if(!dfn[y]){
                dfs(y);
                low[x]=min(low[y],low[x]);
            }
            else if(vis[y]){
                low[x]=min(low[x],dfn[y]);
            }
        }
        if(low[x]==dfn[x])
        {
            num++;
            while(s[top+1]!=x){
                int a=s[top--];
                vis[a]=0;
                col[a]=num;
            }
        }
        return;
    }
    void tarjan()
    {
        cnt=num=top=0;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(vis,0,sizeof(vis));
        memset(col,0,sizeof(col));
        for(int i=1;i<=m*2;++i)
        if(!dfn[i])dfs(i);
    }
    bool solve()
    {
        tarjan();
        for(int i=1;i<=m;++i)if(col[i]==col[i+m])return 0;
        return 1;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            ccnt=0;memset(head,0,sizeof(head));int x,y;
            for(int i=1;i<=m;++i)
            {
                scanf("%d%d",&x,&y);
                if(x>y)swap(x,y);
                p[i].x=x;p[i].y=y;
            }
            for(int i=1;i<=m;++i)
            for(int j=i+1;j<=m;++j){
                if(p[j].x>=p[i].x&&p[j].x<=p[i].y&&p[i].y<=p[j].y||
                p[j].x<=p[i].x&&p[i].x<=p[j].y&&p[j].y<=p[i].y)
                {
                    add(i,j+m);add(i+m,j);
                    add(j,i+m);add(j+m,i);
                }
            }
            if(solve())puts("panda is telling the truth...");
            else puts("the evil panda is lying again");
        }
        return 0;
    }
  • 相关阅读:
    CrackRTFwp 顺便讲讲如何在pe文件中看资源
    开启驱动生涯
    hgame week2 week3
    hgamefinal re peko-chain!
    docker化hbase并使用外部zookeeper
    docker化canal-adapter
    脚本
    ansible模块-user
    esxi克隆虚拟机
    confluence配置搭建
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8303735.html
Copyright © 2011-2022 走看看