• codeforces 469D 2-SAT


    codeforces 469D

    题意:
    n 个数,给出常数 a、b, 要把这 n 个数分成两个不相交的集合 A、B 。且要满足:
    如果某数 x 在 A 里,那么 a-x 也要在 A 里;如果 x 在 B 里,那么 b-x 也要在 B 里。

    tags:
    把 n 个数看成变量,要么在 A,要么在 B,即二判定性,可用 2-SAT 解。对于数 x, 用点 x2 表示它在 A集合,用点 x2+1 表示它在 B 集合。
    但重点是如何连边:
    1】如果对 x ,有 a-x 存在,那么就加双向边 [ x2, (a-x)2 ] , [ x2+1, (a-x)2+1 ] 。
    表示如果 x 在 A集合,那么 a-x 也要在 A集合; 如 x 在 B 集合,那么 a-x 也要在 B集合。
    2】如果对 x, 没有 a-x 存在,那么就加单向边 [ x2, x2+1 ] 。
    表示如果推出了 x 在 A 集合,我们要否定这种情况,把它转回到 B 集合来。

    //  469 D
    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define rep(i,a,b) for (int i=a; i<=b; ++i)
    #define per(i,b,a) for (int i=b; i>=a; --i)
    #define mes(a,b)  memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define MP make_pair
    #define PB push_back
    #define fi  first
    #define se  second
    typedef long long ll;
    const int N = 200005;
    
    int top, Stack[N<<1];
    vector< int > G[N<<1];
    bool mark[N<<1];
    void Addedge(int u, int uval, int v, int vval) {
        u = u*2+uval,  v = v*2+vval;
        G[u].PB(v);
        G[u^1].PB(v^1);
    }
    bool dfs(int u, int fa)
    {
        if(mark[u^1]) return false;
        if(mark[u]) return true;
        mark[u] = true;  Stack[top++] = u;
        for(int to : G[u]) if(!dfs(to, u)) return false;
        return true;
    }
    
    int n, a, b;
    ll  p[N];
    map< ll, int > mp;
    int main()
    {
        scanf("%d%d%d", &n, &a, &b);
        rep(i,1,n) scanf("%d", &p[i]), mp[p[i]]=i;
        bool flag;
        rep(i,1,n) {
            flag = false;
            if(mp.find(a-p[i])!=mp.end()) Addedge(i, 0, mp[a-p[i]], 0), flag=true;
            else  G[i*2].PB(i*2+1);
            if(mp.find(b-p[i])!=mp.end()) Addedge(i, 1, mp[b-p[i]], 1), flag=true;
            else  G[i*2+1].PB(i*2);
            if(!flag) return printf("NO
    "), 0;
        }
        for(int i=2; i<=n*2; i+=2)
        {
            if(mark[i]==false && mark[i^1]==false)
            {
                top = 0;
                if(!dfs(i, 0)) {
                    while(top>0) mark[Stack[--top]] = false;
                    if(!dfs(i^1, 0)) return printf("NO
    "), 0;
                }
            }
        }
        puts("YES");
        for(int i=2; i<=n*2; i+=2)
            if(mark[i]) printf("0 ");
            else  printf("1 ");
        puts("");
    
        return 0;
    }
    
  • 相关阅读:
    mysql 覆盖索引
    mysql 连接查询 和 子查询
    mysql varchar
    uchome 是如何将数据插入数据库的
    Tomcat5 在windows安装服务
    Linux中错误码及描述查看
    Longines浪琴手表型号解释
    perl 安装 Net::Telnet 模块
    php一些错误的显示问题
    firefox样式表cursor和兼容Ie firefox,解决文字溢出的问题(wordwrap:breakword;wordbreak:breakall)
  • 原文地址:https://www.cnblogs.com/sbfhy/p/8590746.html
Copyright © 2020-2023  润新知