HDU 3715 Go Deeper(2-SAT)

来源:互联网 发布:若水软件官网 编辑:程序博客网 时间:2024/04/29 05:07

HDU 3715 Go Deeper(2-SAT)

http://acm.hdu.edu.cn/showproblem.php?pid=3715

题意:

        有下面一个递归程序:

        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

        问你dep最多能达到什么值?由题意可知dep<=m,其中a与b与c数组都是m大小的,数组下标从0到m,然后x数组是下标从0到n-1的.且c数组的取值为0或1或2.a与b数组的取值是0到n-1.x数组的取值是0或1.

现在给出了a,b,c数组对应下标的所有值,但是还不知道x数组的取值,问你如果你来设定x的值,可以使dep最大达到多少?

分析:

        由于x数组只能去0或1,可以看出该题就是2-SAT问题. 我们只要2分dep的值即可的出解.

        假设当前dep=mid,然后对于下标从0到mid-1来说,有下面关系:

        x[a[0]]+x[b[0]] != c[0]

        x[a[1]]+x[b[1]] != c[1]

        

        x[a[mid-1]]+x[b[mid-1]] !=c[mid-1]

        然后我们合理的设置一下x数组的值,看看是否能满足这前mid个条件.由于a,b,c数组的值都已经知道了,比如  a[0]=1,b[0]=2,c[0]=2

        有x[1]+x[2] !=2 ,那么我们可以推出边: add_clause(1,1,2,0)且 add_clause(2,1,1,0).

       一般性结论有:

        x[a]+x[b]= 0 -> add(a,0,b,1)  add(b,0,a,1)

        x[a]+x[b]=1 ->add(a,1,b,1)  add(a,0,b,0) add(b,1,a,1)add(b,0,a,0)

        x[a]+x[b]=2 ->add(a,1,b,0)  add(b,1,a,0)

        二分dep,建图2-SAT,直接解决.

AC代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int maxn= 200 +10;const int maxm= 10000+10;int n,m;int a[maxm],b[maxm],c[maxm];struct TwoSAT{    int n;    vector<int> G[maxn*2];    int S[maxn*2],c;    bool mark[maxn*2];    bool dfs(int x)    {        if(mark[x^1]) return false;        if(mark[x]) return true;        mark[x]=true;        S[c++]=x;        for(int i=0;i<G[x].size();i++)            if(!dfs(G[x][i])) return false;        return true;    }    void init(int n)    {        this->n = n;        for(int i=0;i<2*n;i++) G[i].clear();        memset(mark,0,sizeof(mark));    }    void add_clause(int x,int xval,int y,int yval)    {        x=x*2+xval;        y=y*2+yval;        G[x].push_back(y);    }    bool solve()    {        for(int i=0;i<2*n;i+=2)        if(!mark[i] && !mark[i+1])        {            c=0;            if(!dfs(i))            {                while(c>0) mark[S[--c]]=false;                if(!dfs(i+1)) return false;            }        }        return true;    }}TS;bool ok(int mid){    TS.init(n);    for(int i=0;i<mid;i++)    {        if(c[i]==0)        {            TS.add_clause(a[i],0,b[i],1);            TS.add_clause(b[i],0,a[i],1);        }        else if(c[i]==1)        {            TS.add_clause(a[i],0,b[i],0);            TS.add_clause(a[i],1,b[i],1);            TS.add_clause(b[i],0,a[i],0);            TS.add_clause(b[i],1,a[i],1);        }        else if(c[i]==2)        {            TS.add_clause(a[i],1,b[i],0);            TS.add_clause(b[i],1,a[i],0);        }    }    return TS.solve();}int main(){    int T;    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 L=0,R=m;        while(R>L)        {            int mid = L+(R-L+1)/2;            if(ok(mid)) L=mid;            else R=mid-1;        }        printf("%d\n",L);    }    return 0;}


0 0
原创粉丝点击