zoukankan      html  css  js  c++  java
  • [POI2001] 和平委员会 Peaceful Commission——2-sat(dfs构造字典序最小解)

    题面

      HDU1814

    解析

      2-sat裸题, 求字典序最小的解

      我一开始试图用拓扑序求字典序最小的解,YY了一阵,打完代码,无论如何都要WA,于是弃疗了,至今不知为什么会错,也许是我太菜了吧,于是学习了一下dfs构造字典序最小解的方法,时间复杂度是O(nm)的

      基本思路同拓扑序构造可行解一样,用染色法。但dfs是直接在原图中跑的,因此要传递选择的标记,也就是颜色。从小到大对每一个没有染色的点$j$尝试染上选择的颜色,在对称点$j'$(点$j$的编号小于点$j'$的编号)上染上不选的颜色,传递选择颜色时如果没有遇到不选的颜色,说明染色方案成功,否则失败,再给点$j'$染上选择的颜色 ,点$j$染上不选的颜色,进行相同操作,如果仍然失败,则说明该情况没有可行解。

      HDU上有一个坑点:多组数据。(我的英语菜得不谈,这个东西搞了我半个小时)

     代码:

    #include<cstdio>
    #include<vector>
    using namespace std;
    const int maxn = 8006;
    
    int n, m, stak[maxn], top, col[maxn<<1];
    vector<int> G[maxn<<1];
    
    int mir(int x)
    {
        return x&1? x+1: x-1;
    }
    
    bool paint(int x)
    {
        if(col[x])
            return col[x] == 1;
        col[x] = 1;col[mir(x)] = 2;
        stak[++top] = x;
        for(unsigned int i = 0; i < G[x].size(); ++i)
        {
            int id = G[x][i];
            if(!paint(id))
                return 0;
        }
        return 1;
    }
    
    bool work()
    {
        for(int i = 1; i <= (n<<1); ++i)
            if(!col[i])
            {
                top = 0;
                if(!paint(i))
                {
                    while(top)  col[stak[top]] = col[mir(stak[top])] = 0, top--;
                    if(!paint(mir(i)))
                        return 0;
                }
            }
        return 1;
    }
    
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF)
        {
            for(int i = 1; i <= m; ++i)
            {
                int x, y;
                scanf("%d%d", &x, &y);
                G[x].push_back(mir(y));
                G[y].push_back(mir(x));
            }
            if(work())
            {
                for(int i = 1; i <= (n<<1); ++i)
                    if(col[i] == 1)
                        printf("%d
    ", i);
            }
            else
                printf("NIE
    ");
            for(int i = 1; i <= (n<<1); ++i)
                G[i].clear(), col[i] = 0;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Linux C/C++编程之(三)常用命令之文件处理命令
    linux下查看activiti流程图乱码
    基于区块链的自主身份和可信声明
    数字证书PKI原理
    Linux C/C++编程之(二)常用命令之目录处理命令
    Linux C/C++编程之(一)VMware 虚拟机安装Ubuntu16.04 图解
    移动端专项测试-内存泄漏
    centos7 netstat命令使用场景 杂记
    《java入门第一季》之面向对象(构造方法)
    《java入门第一季》之面向对象this关键字
  • 原文地址:https://www.cnblogs.com/Joker-Yza/p/11312672.html
Copyright © 2011-2022 走看看