zoukankan      html  css  js  c++  java
  • HDOJ3715Go Deeper二分+2sat解题报告

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3715用a[i]表示a[i]对应的x[a[i]]是0,a[i]+n表示是1,则

    当c[i]=0时,不能同时为0,则a[i]->b[i]+n,b[i]->a[i]+n

    当c[i]=1时,a[i]->b[i],b[i]->a[i],a[i]+n->b[i]+n,b[i]+n->a[i]+n;

    当c[i]=2时,a[i]+n->b[i],b[i]+n->a[i];

    最后如果二分枚举深度值,要用到二分枚举

    View Code
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 205
    #define M 10005
    using namespace std;
    int head[2*N],t;
    int dfn[2*N],sc[2*N];
    int stk1[2*N],stk2[2*N],cnt0,cnt1,top1,top2;
    int a[M],b[M],c[M];
    struct node
    {
        int v,next;
    };
    node edge[M*4];
    void init()
    {
        t=0;
        cnt0=cnt1=0;
        top1=top2=0;
        memset(head,-1,sizeof(head));
        memset(dfn,-1,sizeof(dfn));
        memset(sc,-1,sizeof(sc));
    }
    void add(int u,int v)
    {
        edge[t].v=v;
        edge[t].next=head[u];
        head[u]=t++;
    }
    void build(int mid,int n)
    {
        int i;
        for(i=1;i<=mid;i++)
        {
            if(c[i]==0)
            {
                add(a[i],b[i]+n);
                add(b[i],a[i]+n);
            }
            else if(c[i]==1)
            {
                add(a[i],b[i]);
                add(a[i]+n,b[i]+n);
                add(b[i],a[i]);
                add(b[i]+n,a[i]+n);
            }
            else
            {
                add(a[i]+n,b[i]);
                add(b[i]+n,a[i]);
            }
        }
    }
    void gabow(int u)//gabow算法求强连通分量
    {
        dfn[u]=cnt0++;
        stk1[top1++]=u;
        stk2[top2++]=u;
        int i,j,v;
        for(i=head[u];i>=0;i=edge[i].next)
        {
            v=edge[i].v;
            if(dfn[v]==-1)
            gabow(v);
            else if(sc[v]==-1)
            while(dfn[stk2[top2-1]]>dfn[v])
            top2--;
        }
        if(stk2[top2-1]!=u)
        return;
        top2--;
        do
        {
            sc[stk1[--top1]]=cnt1;
        }while(stk1[top1]!=u);
        cnt1++;
    }
    int can(int mid,int n)
    {
        init();
        build(mid,n);
        int i;
        for(i=0;i<2*n;i++)
        if(dfn[i]==-1)
        gabow(i);
        for(i=0;i<n;i++)
        if(sc[i]==sc[i+n])
        return false;
        return true;
    }
    int main()
    {
        int n,m,i,j,ans,low,high,mid;
        int tcase;
        scanf("%d",&tcase);
        while(tcase--)
        {
            scanf("%d%d",&n,&m);
            for(i=1;i<=m;i++)
            scanf("%d%d%d",&a[i],&b[i],&c[i]);
            low=1,high=m;
            ans=1;
            while(low<=high)
            {
                mid=(low+high)>>1;
                if(can(mid,n))
                {
                    ans=mid;
                    low=mid+1;
                }
                else
                high=mid-1;
            }
            printf("%d\n",ans);
        }
        return 0;
    }
  • 相关阅读:
    最大流最小割
    最大权闭合图
    凸包,多边形面积,线段在多边形内的判定。
    模线性方程
    ZOJ Monthly, August 2014
    nenu contest2
    2014 Multi-University Training Contest 10
    Codeforces Round #262 (Div. 2)
    nenu contest
    poj 2299 求逆序数
  • 原文地址:https://www.cnblogs.com/caozhenhai/p/2640675.html
Copyright © 2011-2022 走看看