zoj3422Go Deeper(2-sat + 二分)

题目请戳这里

题目大意:

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;

}


 

 

你可能感兴趣的:(ZOJ)