UVALive 5010 2-sat+二分
来源:互联网 发布:i o接线端口 编辑:程序博客网 时间:2024/06/10 11:24
链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3011
题意:给出a[i], b[i], c[i],构造x[i],求出满足1<=x<=L, c[i] != x[a[i]] + x[b[i]]的最大L,a,b,x是01数组,c使0~2的数组
题解:若加入关系i使得x无法构造,则i+1也无法加入,满足二分性质。对于a[i], b[i], c[i], 可以求出x[a[i]], x[b[i]]不可取的取值,用2-sat维护x[i]的取值判断冲突。
2-sat见
http://blog.csdn.net/cevaac/article/details/39719813
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>using namespace std;const int N = 10010;const int M = 1000000;using namespace std;#define bf(x) ((x)<<1)#define bt(x) ((x)<<1|1)int ind[N], id[N];int t[M], nt[M];int dfn[N], low[N];int s[N];bool vis[N];int l;int n;int cnt, num, idn;int a[N], b[N], c[N];void add(int i, int j){ cnt++; t[cnt] = j; nt[cnt] = ind[i]; ind[i] = cnt;}void tarjan(int x){ num++; dfn[x] = low[x] = num; s[++l] = x; vis[x] = true; for(int k = ind[x]; k != -1; k = nt[k]) { if(dfn[t[k]] == 0) tarjan(t[k]); if(vis[t[k]]) low[x] = min(low[x], low[t[k]]); } if(dfn[x] == low[x]) { idn++; while(true) { int tmp = s[l--]; id[tmp] = idn; vis[tmp] = false; if(tmp == x) break; } }}bool chk(int M){ for(int i = 0; i < 2 * n; i++) ind[i] = -1; cnt = 0; for (int i = 0; i < M; i++) { if (c[i] == 0) { add(bf(a[i]),bt(b[i])); add(bf(b[i]),bt(a[i])); } else if (c[i] == 1) { add(bf(a[i]), bf(b[i])); add(bf(b[i]), bf(a[i])); add(bt(a[i]), bt(b[i])); add(bt(b[i]), bt(a[i])); } else { add(bt(a[i]),bf(b[i])); add(bt(b[i]),bf(a[i])); } } //cout << cnt << endl; memset(vis, 0, sizeof vis); num = 0; idn = 0; l = 0; memset(dfn, 0, sizeof dfn); memset(low, 0, sizeof low); memset(id, 0, sizeof id); for(int i = 0; i < 2 * n; i++) { if(dfn[i] == 0) tarjan(i); } for(int i = 0; i < 2 * n; i++) { if(id[i] == id[i ^ 1]) return false; } return true;}int main(){ //freopen("test.in", "r", stdin); int t; scanf("%d",&t); while (t--) { int m; scanf("%d%d",&n,&m); for(int i = 0; i < m; i++) scanf("%d%d%d", &a[i], &b[i], &c[i]); int l = 0, r = m; while(l < r - 1) { int mid = (l + r) / 2; if(chk(mid)) l = mid; else r = mid; } if(chk(r)) printf("%d\n", r); else printf("%d\n", l); } return 0;}
0 0
- UVALive 5010 2-sat+二分
- UvaLive--3211--Now or later【2-SAT+二分答案】
- UVALive 3211 - Now or later(2-SAT + 二分)
- UVALive 3211 Now or later || 2-sat + 二分
- uvalive 3713 2-sat
- UVALive 3211 2-SAT问题
- UVALive 3713 - Astronauts(2-SAT)
- UVALive - 3713 Astronauts(2-SAT)
- UVALive 3211 (训练指南)图论例题9 2-sat+二分
- HDU3622 二分+2-SAT
- HDOJ3622-2SAT,二分
- POJ2749-二分,2SAT
- poj2296(二分+2sat)
- HDU3622(二分+2-SAT)
- HDU3715(二分+2-SAT)
- hdu3622 二分+2sat
- hdu3715 2-sat+二分
- POJ2296二分2sat
- 我现在想学编程,我该做什么呢?
- 股票数据查询接口
- 《Effective C++ 》学习笔记——条款08
- 黄金数据查询演示示例
- Xshell中文乱码问题
- UVALive 5010 2-sat+二分
- 【转】SQL2008的sa账户被禁用,其他账户无法连接的解决方法
- 几种数据存储的优缺点
- C++在单继承、多继承、虚继承时,构造函数、复制构造函数、赋值操作符、析构函数的执行顺序和执行内容
- 全部开放基金接口调用代码
- 关于Class和Subclass的分类
- C++多重继承之成员变量的偏移量
- 打造象LINUX一样的mac os x 环境
- 以IP地址定义的链接服务器设置别名