您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  2-sat