• poj 2723 2-SAT问题


    思路:二分枚举能开的门的数量,将每次枚举转换成2-SAT问题。这里存在的矛盾是假设有门上a,b两个锁,a锁对应于1号钥匙,而一号钥匙的配对是2号钥匙,b锁对应于3号钥匙,3号的配对是4号钥匙。那么2号和4号就不能同时被选,否则有a,b锁的门就开不了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define Maxn 3010
    #define Maxm 1000000
    using namespace std;
    int dfn[Maxn],low[Maxn],vi[Maxn],head[Maxn],f[Maxn],e,n,m,lab,top,Stack[Maxn],num,id[Maxn],x[Maxn],y[Maxn];
    struct Edge{
        int u,v,next,l;
    }edge[Maxm];
    void init()
    {
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(head,-1,sizeof(head));
        memset(id,0,sizeof(id));
        e=lab=num=top=0;
    }
    void add(int u,int v)
    {
        edge[e].u=u,edge[e].v=v,edge[e].next=head[u],head[u]=e++;
    }
    void Tarjan(int u)
    {
        int i,j,v;
        dfn[u]=low[u]=++lab;
        Stack[top++]=u;
        vi[u]=1;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            if(vi[v])
            low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            ++num;
            do{
                i=Stack[--top];
                vi[i]=0;
                id[i]=num;
            }while(i!=u);
        }
    }
    int solve(int mid)
    {
        int i,j;
        init();
        for(i=1;i<=mid;i++)
        {
            add(f[x[i]],y[i]);
            add(f[y[i]],x[i]);
        }
        for(i=1;i<=n;i++)
            if(!dfn[i])
            {
                Tarjan(i);
            }
        for(i=1;i<=n;i++)
        {
            if(id[i]==id[f[i]])
                return 0;
        }
        return 1;
    }
    int main()
    {
        int i,j,a,b;
        while(scanf("%d%d",&n,&m),n|m)
        {
            init();
            memset(f,0,sizeof(f));
            for(i=1;i<=n;i++)
            {
                scanf("%d%d",&a,&b);
                a++,b++;
                f[a]=b,f[b]=a;
            }
            for(i=1;i<=m;i++)
            {
                scanf("%d%d",x+i,y+i);
                x[i]++,y[i]++;
            }
            n*=2;
            int l,r,mid;
            l=0,r=m+1;
            while(r>l+1)
            {
                mid=(l+r)>>1;
                if(solve(mid))
                    l=mid;
                else
                    r=mid;
            }
            printf("%d
    ",l);
        }
        return 0;
    }
  • 相关阅读:
    dedecms5.7百度主动推送(实时) 开发
    胆囊结石食物选择
    读《遥远的救世主》与观看电视剧天道
    cnn健康增胖和调理好身体
    Machine-wide Progress Telerik Fiddler installation has been found at ...Please, use that one or uninstall it ...
    鼻炎治疗之路(转载)
    学医后才知道的小知识...
    一点浩然气,千里快哉风(修炼孟子浩然之气)
    孟尝君的逆袭
    张小龙和张一鸣的对立统一
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3219909.html
Copyright © 2020-2023  润新知