2-sat + 二分 hdu3715
2017-08-11 16:28
253 查看
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=3715题意为有4个数组,其中a, b, c是给定数组且长度为m。a, b数组中的值在0~n - 1范围内,c数组的值在0~2范围内。有x数组,x数组仅包含0, 1。当x[a[dep]] + x[b[dep]]不等于c[dep]时且dep < m时,dep+=1问能够达到的最大dep是多少。
可以看出x只能取两个状态所以就是2-sat。c为0时,a[dep]和b[dep]所代表的x不能同时为0;c为1时两者要么同时为0要么同时为1;c为2时,两者不能同时为1。建图后就是跑2-sat判断了。
最开始我直接遍历1~m每次分别求2-sat这样建图可以记忆化但是T了。之后二分,枚举答案,每次重新建图判断是否满足条件即可。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <stack> #include <queue> #define rep(i, s, t) for(int i = s;i <= t;i++) #define rap(i, s, t) for(int i = s;i >= t;i--) using namespace std; struct Edge { int v, next; }edge[100004]; int head[405]; int cnt_Edge; int cnt_Bcnt; int Bcnt[405]; int low[405], dfn[405]; int Instack[405]; stack<int>SS; int Index; int n, m; int a[10004], b[10004], c[10004]; void init() { memset(head, -1, sizeof(head)); cnt_Edge = 0; } void add_Edge(int u, int v) { edge[cnt_Edge].v = v; edge[cnt_Edge].next = head[u]; head[u] = cnt_Edge++; } void get_Map(int dep) { rep(i, 0, dep - 1) { int lsa = a[i]; int lsb = b[i]; if(c[i] == 0) add_Edge(lsa<<1, lsb<<1^1), add_Edge(lsb<<1, lsa<<1^1); else if(c[i] == 1) add_Edge(lsa<<1^1, lsb<<1^1), add_Edge(lsb<<1^1, lsa<<1^1), add_Edge(lsa<<1, lsb<<1), add_Edge(lsb<<1, lsa<<1); else if(c[i] == 2) add_Edge(lsa<<1^1, lsb<<1), add_Edge(lsb<<1^1, lsa<<1); } } void tarjan(int a) { low[a] = dfn[a] = ++Index; Instack[a] = 1; SS.push(a); for(int i = head[a];i != -1;i = edge[i].next) { int v = edge[i].v; if(!dfn[v]) { tarjan(v); low[a] = min(low[a], low[v]); } else { if(Instack[v] == 1&&dfn[v] < low[a]) low[a] = dfn[v]; } } if(low[a] == dfn[a]) { int ls; cnt_Bcnt++; do { ls = SS.top(); SS.pop(); Instack[ls] = 0; Bcnt[ls] = cnt_Bcnt; } while(ls != a); } } void find_Scc() { memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(Bcnt, 0, sizeof(Bcnt)); memset(Instack, 0, sizeof(Instack)); cnt_Bcnt = 0; Index = 0; rep(i, 0, 2 * n - 1){ if(!dfn[i]) tarjan(i); } } int solve() { rep(i, 0, n - 1) { if(Bcnt[i<<1] == Bcnt[i<<1^1]) return 0; } return 1; } int main() { int t; scanf("%d", &t); while(t--) { scanf("%d%d", &n, &m); rep(i, 0, m - 1) scanf("%d%d%d", &a[i], &b[i], &c[i]); int l = 1; int r = m; int mid; int ans = 0; while(r >= l) { mid = (l + r)>>1; init(); get_Map(mid); find_Scc(); if(solve()) { l = mid + 1; ans = max(ans, mid); } else r = mid - 1; } printf("%d\n", ans); } return 0; }
相关文章推荐
- hdu3715 Go Deeper--二分 & 2-sat
- hdu3715 2-sat+二分
- hdu3715 2-sat+二分
- HDU3715(二分+2-SAT)
- HDU3715(二分+2-SAT)
- [POJ3622]-Bomb Game-二分答案+2-SAT
- [二分+2-sat]Hdu 3622——Bomb Game
- HDU - 3622 Bomb Game(二分+2-SAT)
- hdu1816 Get Luffy Out *--二分 & 2-sat
- UVa 3211 Now or later (二分+2-Sat)
- HDU 1816 Get Luffy Out *(2-SAT+二分)
- poj 2723 Get Luffy Out 二分+2-sat
- POJ 2723 Get Luffy Out 二分 2-SAT
- zoj3422Go Deeper(2-sat + 二分)
- poj 2749 Building roads 【2-sat + 二分】【建图较复杂】【好题】
- uva 1146(2-SAT+二分判断)
- UVA Live 3211飞机调度问题-二分+2-SAT
- POJ2749-二分,2SAT
- LA 3211 Now or later (2-SAT + 二分)
- POJ 2296 Map Labeler 2-SAT 二分