• 2-SAT


    昨天学弟问我G题是不是2-SAT,尴尬的是我不知道那是什么,所以今天特地来学一下,先来个简单的

    先看一下最经典的题HDU1814和平委员会

    题意:输入n,m代表n个国家,每个国家 i 有两个代表分别是 2*i-1和2*i.m代表有m对冤家,每对冤家不能一起出现在委员会中,问能不能让所有国家都出一个代表构成委员会,可以的话输出n个国家所选出的代表标号,否则输出NIE
    就粘一下输入输出吧
    Sample Input
    3 2
    1 3
    2 4
    Sample Output
    1
    4
    5

    这道题感觉跟2-SAT(仅限我现在理解的)有关系,还感觉没啥关系

    oth(x)代表和x是一个国家的那个人的编号

    做法就是如果 i 和 j 是冤家那么 选 i 就要选 oth(j) ,选 j 就要选 oth(i) 然后从1~2*n开始遍历

    数组 f 初始是0,1代表选中,2代表不选

    对于第 i 个遇到 f[i] 是0,那么先试试 选 i ,即 f[i]=1,f[oth(i)]=2

    如果选了一个那么边相连的就都要选,如果边相连是2了,说明决策不对则f[i]=2,f[oth(i)]=1,若还不行那么无解

    最后把f[i]=1的 i 输出就可以了

    #include<stdio.h>
    #include<string.h>
    #define rep(i,j,k) for(int i=j;i<=k;++i)
    #define oth(x) (x%2==0?x-1:x+1)
    struct s
    {
        int to,next;
    } edge[40005];
    int head[16005];
    int cnt;
    void add(int x,int y)
    {
        edge[cnt].to=y;
        edge[cnt].next=head[x];
        head[x]=cnt++;
    }
    int tot;
    int f[16005],ff[160005];
    bool paint(int x)
    {
        if(f[x]!=0)
            return f[x]%2;
        f[x]=1;
        f[oth(x)]=2;
        ff[tot++]=x;
        for(int i=head[x]; i!=-1; i=edge[i].next)
        {
            if(!paint(edge[i].to))
                return false;
        }
        return true;
    }
    int n;
    bool solve()
    {
        rep(i,1,2*n)
        {
            if(f[i])
                continue;
            tot=0;
            if(!paint(i))
            {
                rep(j,0,tot-1)
                {
                    f[ff[j]]=0;
                    f[oth(ff[j])]=0;
                }
                if(!paint(oth(i)))
                    return false;
            }
        }
        return true;
    }
    int main()
    {
        int m;
        while(scanf("%d %d",&n,&m)!=EOF)
        {
            memset(head,-1,sizeof(head));
            memset(f,0,sizeof(f));
            cnt=0;
            int x,y;
            rep(i,1,m)
            {
                scanf("%d %d",&x,&y);//oth(x)是x的搭档
                add(x,oth(y));//选x就只能选y的搭档
                add(y,oth(x));
            }
            if(solve())
            {
                rep(i,1,2*n)
                if(f[i]==1)
                    printf("%d
    ",i);
            }
            else
                printf("NIE
    ");
        }
    }
  • 相关阅读:
    vue表单验证定位到错误的地方
    INSPINIA Version 2.5 Bootstrap3
    volatile 彻底搞懂
    solr6.4.2之webservice兼容升级
    快速排序
    Elasticsearch调优篇 10
    TCP 连接为什么需要 3 次握手和 4 次挥手
    搜索技术与方案的选型与思考
    Elasticsearch调优篇 09
    Elasticsearch调优篇 08
  • 原文地址:https://www.cnblogs.com/lmhyhblog/p/9129853.html
Copyright © 2020-2023  润新知