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

来源:互联网 发布:快手制作视频软件 编辑:程序博客网 时间:2024/06/05 16:50

给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 | 1const 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