CF -- 468B Two Set (2-SAT)

3 篇文章 0 订阅
1 篇文章 0 订阅

给n个互不相等的整数,要把他们分成两个集合。如果x属于集合A,那么a-x也要属于;如果x属于集合B,那么b-x也要属于。问能不能找到这样的解,有解的话输出解。如果第i个元素属于A,输出0;如果属于B输出1.

http://codeforces.com/problemset/problem/468/B

好久不做2-SAT。。。。

首先,这n个数都是互不相同的。也就是说,对于每个数x,最多有一个y,使得x + y = a;同样最多有一个z,使得x + z = b。

如果y和z都不存在,那就一定无解,直接输出“NO”。

如果z不存在y存在,那么就说明x和y一定属于一个集合。我们连边mp[x]--mp[y], mp[x]'--mp[y]',这里mp[i] = 值为i的元素编号。

y不存在z存在也是一样的。

那么y和z要是都存在呢?x和y一个集合,或者x和z一个集合。这有3个点可怎么连边~~o(>_<)o ~~

想一想。。。。。

发现y和z不能属于同一集合,也就是他们之间存在异或关系。连mp[y]'--mp[z],mp[y]--mp[z]'.

好像顺利解决了。。!

。。。突然发现如果y或者z = x,这样连边就矛盾了。+_+ 

嗯。。。矛盾了无非就是u连了v又连了v'。。。就是u可以和v一个集合,也可以不和v一个集合。。。。相当于废话。直接不连就好了。。!

然后就是要输出解。。。

2-sat输出路径实在好麻烦。。又是缩点啊,又是拓扑排序啊,又是染色啊。。。。。

直接判断x,y,z的id,x和y一样就输出0,和z一样就输出1.当然还要考虑y或z和x相等的情况。

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef double DB;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;

#define pb push_back
#define MP make_pair
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

const DB eps = 1e-8;
const int inf = 0x3f3f3f3f;
const int mod = 10000007;
const int maxn = 200000 + 10;

int n, a, b, p[maxn];
map<int, int> mp;
map<int, int> ::iterator it;
struct node{
    int v, next;
}edge[2000000];
int head[maxn], cnt, dfn[maxn], low[maxn], used[maxn], id[maxn], sz, idx;
stack<int> sta;
void addedge(int u, int v){
    edge[cnt].v = v; edge[cnt].next = head[u]; head[u] = cnt++;
    //cout <<"u:" << u << ", v:" << v <<endl;
}
void Tarjan(int x){
    dfn[x] = low[x] = ++idx;
    sta.push(x);
    used[x] = 1;
    for(int i=head[x]; ~i; i=edge[i].next){
        int k = edge[i].v;
        if(!dfn[k]){
            Tarjan(k);
            low[x] = min(low[x], low[k]);
        }else if(used[k]) low[x] = min(dfn[k], low[x]);
    }
    if(dfn[x] == low[x]){
        sz++;
        int k;
        do{
            k = sta.top(); sta.pop();
            used[k] = 0;
            id[k] = sz;
        }while(k != x);
    }
}
bool Two_SAT(){
    idx = sz = 0;
    memset(dfn, 0, sizeof(dfn));
    while(!sta.empty()) sta.pop();
    for(int i=0; i<2*n; i++)
        if(!dfn[i]) Tarjan(i);
//    for(int i=0; i<2*n; i++)
//        printf("%d %d\n", i, id[i]);
    for(int i=0; i<n; i++)
        if(id[i] == id[i + n]) return false;
    return true;
}
bool cal(){
    for(int i=0; i<n; i++){
        int cnt = 0, y = a - p[i], z = b - p[i];
        if((it = mp.find(y)) != mp.end()){
            cnt |= 1;
        }
            if((it = mp.find(z)) != mp.end()){
            cnt |= 2;
        }
        if(!cnt)return false;
        if(cnt == 1){///x&y
            if(p[i] != y) {addedge(i, mp[y]); addedge(mp[y], i); addedge(i + n, mp[y] + n); addedge(mp[y] + n, i + n);}
        }else if(cnt == 2){///x&z
            if(p[i] != z) {addedge(i, mp[z]); addedge(mp[z], i); addedge(i + n, mp[z] + n); addedge(mp[z] + n, i + n);}
        }else if(y == z){///x&y
            if(p[i] != y) {addedge(i, mp[y]); addedge(mp[y], i); addedge(i + n, mp[y] + n); addedge(mp[y] + n, i + n);}
        }else if(y != p[i] && z != p[i]){///y^z
            int yy = mp[y], zz = mp[z];
            addedge(yy, zz + n); addedge(zz, yy + n); addedge(yy + n, zz); addedge(zz + n, yy);
        }
    }
    if(!Two_SAT()) return false;
    return true;
}
int main(){
    while(scanf("%d%d%d", &n, &a, &b) == 3){
        mp.clear();
        memset(head, -1, sizeof(head)); cnt = 0;
        for(int i=0; i<n; i++){
            scanf("%d", &p[i]);
            mp[p[i]] = i;
        }
        if(!cal()) {puts("NO"); continue;}
        else puts("YES");

        for(int i=0; i<n; i++){
            int y = a - p[i], z = b - p[i], flag = 0;
            if((it = mp.find(y)) != mp.end()){
                flag |= 1;
            }
            if((it = mp.find(z)) != mp.end()){
                flag |= 2;
            }
            if(flag == 1) printf("0 ");
            else if(flag == 2) printf("1 ");
            else if(p[i] == y && id[i] == id[mp[z]]) printf("1 ");
            else if(p[i] == z && id[i] == id[mp[y]]) printf("0 ");
            else{
                if(id[i] == id[mp[z]]) printf("1 ");
                else printf("0 ");
            }
        }
        puts("");
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值