[bzoj1997][2-sat]Planar

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Rose_max/article/details/82181658

Description

这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

Sample Input

2

6 9

1 4

1 5

扫描二维码关注公众号,回复: 2994953 查看本文章

1 6

2 4

2 5

2 6

3 4

3 5

3 6

1 4 2 5 3 6

5 5

1 2

2 3

3 4

4 5

5 1

1 2 3 4 5

Sample Output

NO

YES

题解

第一次做有关平面图的问题
先记下一个结论:对于一个极大简单平面图G(n,m),总有m<=3*n-6
发现如果两条线段在圈内会相交,在圈外也会相交
暴力枚举两条线段判相交情况,建边2-sat判可行性
m很大但可以用上面那个结论剪枝
就愉快地 n 2

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
struct pt{int c,op;}g[15];
bool cmp(pt n1,pt n2){return (n1.c!=n2.c)?(n1.c<n2.c):(n1.op<n2.op);}
struct edge{int x,y;}w[10005];
struct node{int x,y,next;}a[400005];int len,last[1205];
void ins(int x,int y){len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int low[1205],dfn[1205],sta[1205],belong[1205],id,cnt,tp,n,m;
bool v[1205];
void tarjan(int x)
{
    low[x]=dfn[x]=++id;sta[++tp]=x;
    v[x]=true;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dfn[y]==-1)tarjan(y),low[x]=min(low[x],low[y]);
        else if(v[y])low[x]=min(low[x],dfn[y]);
    }
    if(low[x]==dfn[x])
    {
        int i;cnt++;
        do
        {
            i=sta[tp--];
            belong[i]=cnt;
            v[i]=false;
        }while(i!=x);
    }
}
int ring[1205],pos[1205];
bool check(int x,int y)
{
    int u=pos[x];
    if(ring[u+1]!=y&&ring[u-1]!=y)return true;
    return false;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&w[i].x,&w[i].y);
        for(int i=1;i<=n;i++)scanf("%d",&ring[i]),pos[ring[i]]=i;
        ring[0]=ring[n];ring[n+1]=ring[1];
        if(m>3*n-6){puts("NO");continue;}
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=m;i++)
            if(check(w[i].x,w[i].y))
                for(int j=i+1;j<=m;j++)
                    if(check(w[j].x,w[j].y))
                    {
                        int s1=pos[w[i].x],s2=pos[w[i].y];if(s1>s2)swap(s1,s2);
                        int s3=pos[w[j].x],s4=pos[w[j].y];if(s3>s4)swap(s3,s4);
                        if(s1==s3||s1==s4||s2==s3||s2==s4)continue;
                        g[1].c=s1;g[1].op=1;g[2].c=s2;g[2].op=1;
                        g[3].c=s3;g[3].op=2;g[4].c=s4;g[4].op=2;
                        sort(g+1,g+1+4,cmp);
                        if(g[1].op==g[3].op)ins(i,j+m),ins(i+m,j),ins(j,i+m),ins(j+m,i);
                    }
        memset(dfn,-1,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(v,false,sizeof(v));
        id=cnt=tp=0;
        for(int i=1;i<=2*m;i++)if(dfn[i]==-1)tarjan(i);
        bool bk=true;
        for(int i=1;i<=m;i++)if(belong[i]==belong[i+m]){bk=false;break;}
        if(bk)puts("YES");
        else puts("NO");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Rose_max/article/details/82181658
今日推荐