题意:给了你一个递归方程,在满足条件x[a[dep]] + x[b[dep]] != c[dep]下最多能到第几层递归。其中a[ ],b[ ],c[ ]数组都是给定的,而x[]不是给定的。
看这个条件,正因为x[ ]不是给定的,所以这是一个2-SAT问题,而m最多是10000,直接线性复杂度的话会超时,所以要二分求dep的最大值,每次把前dep层的矛盾关系都建边。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m;
int a[10005];
int b[10005];
int c[10005];
const int MAXN = 200020;
const int MAXM = 200010;
#define LL long long
struct Edge {
int to, next;
} edge[MAXM];
int head[MAXN], cntE;
void init() {
cntE = 0;
memset(head, -1, sizeof head);
}
void addedge(int u, int v) {
edge[cntE].to = v;
edge[cntE].next = head[u];
head[u] = cntE++;
}
bool vis[MAXN];
int stk[MAXN], top;
bool dfs(int u) {
if (vis[u ^ 1]) return false;
if (vis[u]) return true;
vis[u] = true; stk[top++] = u;
for (int i = head[u]; ~i; i = edge[i].next) {
if (!dfs(edge[i].to)) return false;
}
return true;
}
inline bool sat(int n) {
memset(vis, false, sizeof vis);
for (int i = 0; i < n; ++i) {
if (vis[i] || vis[i ^ 1]) continue;
top = 0;
if (!dfs(i)) {
while (top) vis[stk[--top]] = false;
if (!dfs(i ^ 1)) return false;
}
}
return true;
}
int T;
bool ok(int mid)
{
for (int i = 0; i < mid; i++)
{
int u = a[i];
int v = b[i];
u *= 2;
v *= 2;
if (c[i] == 0)
{
addedge(u ^ 1, v);
addedge(v ^ 1, u);
}
else if (c[i] == 1)
{
addedge(u ^ 1, v ^ 1);
addedge(v ^ 1, u ^ 1);
addedge(u, v);
addedge(v, u);
}
else
{
addedge(u, v ^ 1);
addedge(v, u ^ 1);
}
}
return sat(mid * 2);
}
int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &m);
for (int i = 0; i < m; i++) scanf("%d %d %d", &a[i], &b[i], &c[i]);
int low = 1, high = m;
while (low < high)
{
init();
int mid = (low + high + 1) >> 1;
if (ok(mid)) low = mid;
else high = mid - 1;
}
printf("%d\n", low);
}
}