可行性nullpoj 2723 Get Luffy Out 2sat

最近研究可行性null,稍微总结一下,以后继续补充:

    二分+2sat判可行性

    每日一道理
最为值得珍惜的是今天,因为最容易流逝的就是今天,把握今天就是把握希望,分分秒秒只是瞬间,而所乘载的分分秒秒就叫做一天,时间的流逝往往是在不经意之间,人生几回,青春更珍贵,对于我们这个年龄的青少年来说,青春已不足二十载,在学习的生活中我们必须靠自己的力量,驾驭着自己的小船驶向希望的彼岸。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1024*2+9;
int doorx[1<<12],doory[1<<12],x[maxn],y[maxn];
int n,m;
int dfn[maxn<<1],low[maxn<<1],stack[maxn<<1],instack[maxn<<1],s[maxn<<1];
int count,top,con;
int head[maxn<<1],lon;
struct
{
    int next,to;
}e[1000000];
void edgemake(int from,int to)
{
    e[++lon].to=to;
    e[lon].next=head[from];
    head[from]=lon;
}
void edgeini()
{
    memset(head,-1,sizeof(head));
    lon=-1;
}
void tarjan(int t)
{
    dfn[t]=low[t]=++count;
    stack[++top]=t;
    instack[t]=1;
    for(int k=head[t];k!=-1;k=e[k].next)
    {
        int u=e[k].to;
        if(dfn[u]==-1)
        {
            tarjan(u);
            low[t]=min(low[t],low[u]);
        }
        else if(instack[u]==1)
        low[t]=min(low[t],dfn[u]);
    }
    if(dfn[t]==low[t])
    {
        ++con;
        while(1)
        {
            int u=stack[top--];
            instack[u]=0;
            s[u]=con;
            if(u==t) break;
        }
    }
}
void tarjan()
{
    memset(dfn,-1,sizeof(dfn));
    memset(instack,0,sizeof(instack));
    count=top=con=0;
    for(int i=0;i<=n*2*2-1;i++)
    if(dfn[i]==-1)
    tarjan(i);
}

bool check()
{
    for(int i=0;i<=n*4-1-1;i+=2)
    if(s[i]==s[i+1])
    return false;
    return true;
}

bool check(int ret)
{
    edgeini();
    for(int i=1;i<=n;i++)
    {
        edgemake(x[i]*2,y[i]*2+1);
        edgemake(y[i]*2,x[i]*2+1);
    }
    for(int i=1;i<=ret;i++)
    {
        edgemake(2*doorx[i]+1,2*doory[i]);
        edgemake(2*doory[i]+1,2*doorx[i]);
    }
    tarjan();

    return check();
}



int main()
{
    while(scanf("%d %d",&n,&m),n||m)
    {
        edgeini();
        for(int i=1,tmp;i<=n;i++)
        {
            scanf("%d %d",&x[i],&y[i]);
        }
        for(int i=1;i<=m;i++)
        scanf("%d %d",&doorx[i],&doory[i]);
        int st=0,ed=m;
        while(st<ed)
        {
            int mid=(st+ed+1)>>1;
            if(check(mid))
            st=mid;
            else
            ed=mid-1;
        }
        printf("%d\n",st);
    }
    return 0;
}

文章结束给大家分享下程序员的一些笑话语录: 神灯新篇
一个程序员在海滩上发现了一盏神灯。他在灯上擦了几下,一个妖怪就从灯里跳出来说:“我是世界上法术最强的妖怪。我可以实现你的任何梦想,但现在,我只能满足你一个愿望。”程序员摊开了一幅中东地图说:“我想让中东得到永久的和平。”妖怪答道:“哦,我没办法。自打创世纪以来,那里的战火就没有停息过。这世上几乎没有我办不到的事,但这件事除外。”程序员于是说:“好吧,我是一个程序员,为许多用户编写过程序。你能让他们把需求表述得更清楚些,并且让我们的软件项目有那么一两次按进度按成本完成吗?”妖怪说:“唔,我们还是来看中东地图吧。”

原文地址:https://www.cnblogs.com/jiangu66/p/3093743.html