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
- CF -- 468B Two Set (2-SAT)
- codeforces 468B Two Sets 2-sat
- CF - 223 - B. Two Strings
- codeforces 468B 2-sat
- cf 468B Two Sets | dfs、二分搜索
- cf 520 B. Two Buttons bfs
- CF 141 div2 D(2-SAT)
- CF 510B(Fox And Two Dots-图上找环)
- cf#ECR 9-B. Alice, Bob, Two Teams-DP
- cf#AIM Tech Round -B. Making a String-贪心/set
- 【打CF,学算法——二星级】CF 520B Two Buttons
- CF 2 B(dp)
- CF #230 (Div. 2) B
- CF #133(DIV.2) B
- CF #257 (Div. 2) B.
- CF#256 (Div. 2) B.
- CF#FF (Div. 2) B.
- CF#254 (Div. 2) B.
- Android开发学习 之 五、基本界面控件
- 静态方法使用
- 生成索引信息及索引创建脚本
- javascript 的错误隔离
- apns -> 注册推送功能时发生错误, 错误信息: Error Domain=NSCocoaErrorDomain Code=3000 "未找到应用程序的“aps-environment”的授权字
- CF -- 468B Two Set (2-SAT)
- Robotium 5.0.1 源码解析之控件搜索
- 直接通过ADO操作Access数据库(修改版)
- Pattern正则
- js获取网页高度
- Leetcode_num12_Search Insert Position
- PHP采集 抓取
- Linux系统之工具篇(一)DRBD Centos6.5(64bit)编译安装,双主模式
- MySQL 按指定字段自定义列表排序