BZOJ 1997 [Hnoi2010]Planar - 2-sat

By Euler's formula: n-m+r=2, n vertices, m edges, r surfaces
For simple maximal planar graphs, 3r=2m (each face consists of three edges, and one side is shared by two faces)
Substituted m=3n-6

By m<=3n-6 branching, m was controlled within 1000.

Plane graphs, that is, there is no intersection of line segments, and this problem has given a ring, so there are only two cases of line segments on each non-ring, one is outside the ring, the other is inside the ring, if two line segments intersect, it is not a plane graph.
To determine the relationship between two lines, if the coordinates of the two lines intersect, it must not be taken out or inside at the same time, because there are only two states, just like the two states in 2-sat. Force one to take out while the other must take in, plus constraints to run a tarjan.

What a ghost is the method of intersecting the line segments on the internet? It's surprising that they are the same. For the line segment across n~1, it is obviously necessary to make a special judgement... Fortunately, the data is weak (fog)

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>

using namespace std;

const int maxn=20005;
const int maxm=1000005;

struct edge
{
    int to,next;
}e[maxm];

int cnt,n,m,T,scnt,scccnt,dfs_clock,ecnt;
int stack[maxn],dfn[maxn],low[maxn],head[maxn],belong[maxn],x[maxm],y[maxm],Nr[maxm];
bool inq[maxn];

int read()
{
    int x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
    return x;
}
void insert(int a,int b)
{
    e[++cnt].to=b;e[cnt].next=head[a];head[a]=cnt;
}
void tarjan(int u)
{
    dfn[u]=low[u]=++dfs_clock;
    inq[u]=true;
    stack[++scnt]=u;
    for(int i=head[u];i;i=e[i].next)
    {
        int v=e[i].to;
        if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
        else if(inq[v])low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u])
    {
        scccnt++;
        int now=-1;
        while(now!=u)
        {
            now=stack[scnt--];
            inq[now]=false;
            belong[now]=scccnt;
        }
    }
}
bool cross(int i,int j)
{
    return ((x[j]-x[i])*(x[j]-y[i])>0&&(y[j]-y[i])*(y[j]-x[i])<0)
         ||((x[j]-x[i])*(x[j]-y[i])<0&&(y[j]-y[i])*(y[j]-x[i])>0);
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {   
        scccnt=dfs_clock=cnt=ecnt=0;
        memset(head,0,sizeof head);
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        n=read(),m=read();
        for(int i=1;i<=m;i++)
            x[i]=read(),y[i]=read();
        for(int i=1,t;i<=n;i++)
            t=read(),
            Nr[t]=i;
        if(m>3*n-6)
        {
            puts("NO");
            continue;
        }
        for(int i=1;i<=m;i++)
        {
            x[i]=Nr[x[i]];
            y[i]=Nr[y[i]];
            if(x[i]>y[i])swap(x[i],y[i]);
            if(y[i]-x[i]==1||(x[i]==1&&y[i]==n))
                continue;
            x[++ecnt]=x[i];
            y[ecnt]=y[i];
        }
        for(int i=1;i<=ecnt;i++)
            for(int j=i+1;j<=ecnt;j++)
            {
                if(cross(i,j))
                {
                    insert((i<<1),(j<<1)^1);
                    insert((i<<1)^1,(j<<1));
                    insert((j<<1),(i<<1)^1);
                    insert((j<<1)^1,(i<<1));
                }
            }
        for(int i=2;i<=2*ecnt+1;i++)
            if(!dfn[i])tarjan(i);
        bool ok=true;
        for(int i=1;i<=ecnt;i++)
            if(belong[i<<1]==belong[(i<<1)+1])
            {
                ok=false;
                break;
            }
        puts(ok?"YES":"NO");
    }
}

Posted by nonexist on Fri, 08 Feb 2019 00:21:18 -0800