BZOJ1997 [Hnoi2010]Planar

本文介绍如何利用2-SAT算法解决平面图问题,并通过具体代码实现验证算法的有效性。文章首先阐述了平面图的基本定理,随后通过剪枝策略减少计算复杂度,最终通过2-SAT算法判断给定的边集是否构成平面图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标签:2-sat,平面图

题目

题目传送门

Description

Input

Output

Sample Input

2

6 9

1 4

1 5

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
HINT

Source

Day1

分析

平面图的定理: m<=3n6

可以用这个剪枝

反正用2-sat乱搞了啊qwq

code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mem(x,num) memset(x,num,sizeof x)
#define reg(x) for(int i=last[x];i;i=e[i].next)
using namespace std;
inline ll read()
{
    ll f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int maxn=1e5+6;
int u[maxn],v[maxn],c[maxn],pos[maxn],last[maxn],que[maxn],belong[maxn];
int cnt=1,n,m,low[maxn],dfn[maxn],ind,top,scc,Que;
bool inq[maxn];
struct edge{int to,next;}e[maxn<<2];

void insert(int u,int v){e[++cnt]=(edge){v,last[u]};last[u]=cnt;}

void tarjan(int x){
    low[x]=dfn[x]=++ind;
    inq[x]=1;que[++top]=x;
    reg(x)
        if(!dfn[e[i].to])tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]);
        else if(inq[e[i].to])low[x]=min(low[x],dfn[e[i].to]);
    if(low[x]==dfn[x]){
        scc++;  
        int now=-1;
        while(now!=x){
            now=que[top--];inq[now]=0;
            belong[now]=scc;
        }
    }
}

bool jud()
{
    rep(i,1,m)
        if(belong[2*i]==belong[2*i-1])return 0;
    return 1;
}
int main()
{
    Que=read();
    while(Que--){
        n=read(),m=read();
        rep(i,1,m)u[i]=read(),v[i]=read();
        mem(last,0);cnt=1;scc=ind=0;
        mem(low,0);mem(dfn,0);
        rep(i,1,n)c[i]=read();
        if(m>3*n-6){puts("NO");continue;}
        rep(i,1,n)pos[c[i]]=i;
        top=0;
        rep(i,1,m){
            v[i]=pos[v[i]];u[i]=pos[u[i]];
            if(u[i]>v[i])swap(u[i],v[i]);
            if(v[i]-u[i]==1||(v[i]==n&&u[i]==1))continue;
            u[++top]=u[i],v[top]=v[i];
        }
        m=top;
        rep(i,1,m)
            rep(j,i+1,m)
                if((u[i]<u[j]&&u[j]<v[i]&&v[i]<v[j])||(u[j]<u[i]&&u[i]<v[j]&&v[j]<v[i]))
                {
                    insert(2*i-1,2*j);
                    insert(2*i,2*j-1);
                    insert(2*j-1,2*i);
                    insert(2*j,2*i-1);
                }
        top=0;
        rep(i,1,2*m)
            if(!dfn[i])tarjan(i);
        if(jud())puts("YES");
        else puts("NO");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值