zoj3422Go Deeper(2-sat + 二分)

来源:互联网 发布:帝陀 知乎 编辑:程序博客网 时间:2024/04/29 04:48

题目请戳这里

题目大意:

go(int dep, int n, int m)     begin        output the value of dep.       if dep < m and x[a[dep]] + x[b[dep]] != c[dep] then go(dep + 1, n, m)   end 
读上面程序段,yy出函数功能。数组a,b,c长度为m,x长度为n。数组a,b中元素范围[0,n - 1],数组c元素为0或1或2。x数组元素为1或0。求能输出的最大的m。

题目分析:2-sat,还是比较裸的吧。要求最大的m,所以对长度m二分。

详情请见代码:

#include <iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N = 405;const int M = 10005;struct node{    int to,next;}g[M];int head[N],stack1[N],stack2[N],vis[N],scc[N];int n,m,num;bool flag;int a[M],b[M],c[M];void init(){    memset(head,-1,sizeof(head));    flag = true;    memset(vis,0,sizeof(vis));    memset(scc,0,sizeof(scc));    stack1[0] = stack2[0] = 0;    num = 0;}void build(int s,int e){    g[num].to = e;    g[num].next = head[s];    head[s] = num ++;}void dfs(int cur,int &sig,int &cnt){    if(flag == false)        return;    vis[cur] = ++ sig;    stack1[++stack1[0]] = cur;    stack2[++stack2[0]] = cur;    for(int i = head[cur];~i;i = g[i].next)    {        if(!vis[g[i].to])            dfs(g[i].to,sig,cnt);        else        {            if(scc[g[i].to] == 0)                while(vis[stack2[stack2[0]]] > vis[g[i].to])                    stack2[0] --;        }    }    if(stack2[stack2[0]] == cur)    {        stack2[0] --;        cnt ++;        do        {            scc[stack1[stack1[0]]] = cnt;            if(scc[stack1[stack1[0]]^1] == cnt)            {                flag = false;                return;            }        }while(stack1[stack1[0] --] != cur);    }}void Gabow(){    int i,sig,cnt;    sig = cnt = 0;    for(i = 0;i < n + n && flag;i ++)        if(!vis[i])            dfs(i,sig,cnt);}void solve(){    int l,r,mid;    int ans,i;    l = 0;r = m;    while(l <= r)    {        mid = (l + r)>>1;        init();        for(i = 0;i < mid;i ++)        {            int u = a[i]<<1;            int v = b[i]<<1;            if(c[i] == 0)// !=0            {                build(u,v^1);                build(v,u^1);            }            if(c[i] == 1)// != 1            {                build(u,v);                build(v,u);                build(u^1,v^1);                build(v^1,u^1);            }            if(c[i] == 2)// != 2            {                build(u^1,v);                build(v^1,u);            }        }        Gabow();        if(flag)        {            ans = mid;            l = mid + 1;        }        else            r = mid - 1;    }    printf("%d\n",ans);}int main(){    int i,t;    scanf("%d",&t);    while(t --)    {        scanf("%d%d",&n,&m);        for(i = 0;i < m;i ++)            scanf("%d%d%d",&a[i],&b[i],&c[i]);        solve();    }    return 0;}