zoukankan      html  css  js  c++  java
  • bzoj1997 [Hnoi2010]Planar——2-SAT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1997

    神奇的经典2-SAT问题!

    对于两个相交的区间,只能一里一外连边,所以可以进行2-SAT问题的建模;

    但 m 太大了,可以用一个平面图的定理,m <= 3*n - 6 来缩小范围;

    注意特判要等读入结束后再判掉!!!

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=2005,maxm=10005;//
    int n,m,T,hd[maxn],ct,dfn[maxn],low[maxn],cr,col[maxn];
    int tim,l[maxn],r[maxn],a[maxn],sta[maxn],top;
    bool vis[maxn];
    struct N{
        int to,nxt;
        N(int t=0,int n=0):to(t),nxt(n) {}
    }ed[maxn*maxn*2];
    void add(int x,int y){ed[++ct]=N(y,hd[x]); hd[x]=ct;}
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tim;
        sta[++top]=x; vis[x]=1;
        for(int i=hd[x],u;i;i=ed[i].nxt)
        {
            if(!dfn[u=ed[i].to])tarjan(u),low[x]=min(low[x],low[u]);
            else if(vis[u])low[x]=min(low[x],dfn[u]);
        }
        if(low[x]==dfn[x])
        {
            cr++; int y;
            while((y=sta[top])!=x){top--; vis[y]=0; col[y]=cr;}
            top--; vis[x]=0; col[x]=cr;
        }
    }
    int main()
    {
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++)scanf("%d%d",&l[i],&r[i]);
            for(int i=1,x;i<=n;i++)scanf("%d",&x),a[x]=i;
            if(m>3*n-6){printf("NO
    "); continue;}//先读完再判NO!!! 
            int tp=0;
            for(int i=1;i<=m;i++)
            {
                l[i]=a[l[i]],r[i]=a[r[i]];
                if(l[i]>r[i])swap(l[i],r[i]);
    //            if(r[i]-l[i]==1||(r[i]==n&&l[i]==1))continue;//没有也可 
    //            l[++tp]=l[i],r[tp]=r[i];
            }
    //        m=tp;
            ct=0; memset(hd,0,sizeof hd);
            for(int i=1;i<=m;i++)
                for(int j=i+1;j<=m;j++)
                {
                    if((l[i]<l[j]&&r[i]<r[j]&&r[i]>l[j])||(l[j]<l[i]&&r[j]<r[i]&&r[j]>l[i]))
                        add(i,j+m),add(j+m,i),add(j,i+m),add(i+m,j);
                }
            tim=0; top=0; cr=0;
            memset(low,0,sizeof low);
    //        memset(col,0,sizeof col);
            memset(dfn,0,sizeof dfn);
            for(int i=1;i<=m*2;i++)
                if(!dfn[i])tarjan(i);
            bool fl=0;
            for(int i=1;i<=m;i++)
                if(col[i]==col[i+m]){fl=1; break;}
            if(fl)printf("NO
    ");
            else printf("YES
    ");
        }
        return 0;
    }
  • 相关阅读:
    SEO网站优化10大要点
    三维翻动效果的jquery特效代码
    多款国外虚拟主机简单比较
    jquery同步调用ajax
    3D虚拟技术
    最简单jquery.ajax+php例子(对话框显示文本框输入内容),以小见大(初学手记)
    正则表达式学习博客
    关于XHTML头部声明,什么是DOCTYPE?
    Iframe高度自适应(兼容IE/Firefox、同域/跨域)
    3D立体产业链的发展现状和趋势
  • 原文地址:https://www.cnblogs.com/Zinn/p/9280403.html
Copyright © 2011-2022 走看看