您的位置:首页 > 编程语言 > Go语言

HDU 3715 Go Deeper【2-SAT+二分】

2017-06-30 21:57 411 查看
题目链接

题意:给了你一个递归方程,在满足条件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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM