zoukankan      html  css  js  c++  java
  • [Hnoi2010]Planar

    平面图判定

    题目描述

    若能将无向图 $G=(V, E)$ 画在平面上使得任意两条无重合顶点的边不相交,则称 $G$ 是平面图。判定一个图是否为平面图的问题是图论中的一个重要问题。现在假设你要判定的是一类特殊的图,图中存在一个包含所有顶点的环,即存在哈密顿回路。

    输入输出格式

    输入格式:

    输入文件的第一行是一个正整数 $T$,表示数据组数 (每组数据描述一个需要判定的图)。接下来从输入文件第二行开始有 $T$ 组数据,每组数据的第一行是用空格隔开的两个正整数 $N$ 和 $M$,分别表示对应图的顶点数和边数。紧接着的 $M$ 行,每行是用空格隔开的两个正整数 $u$ 和 $v$ $left(1leq u,vleq N ight)$,表示对应图的一条边 $left(u,v ight)$, 输入的数据保证所有边仅出现一次。每组数据的最后一行是用空格隔开的 $N$ 个正整数,从左到右表示对应图中的一个哈密顿回路:$V_1,V_2,…,V_N$,即对任意 $i ot=j$ 有 $V_i ot=V_j$ 且对任意 $1leq ileq N-1$ 有 $left(V_i,V_i-1 ight)in E$ 及 $left(V_1,V_N ight)in E$。输入的数据保证 $100\%$ 的数据满足 $Tleq100,3leq Nleq200,Mleq10000$。

    输出格式:

    包含 $T$ 行,若输入文件的第 $i$ 组数据所对应图是平面图,则在第 $i$ 行输出 $ ext{YES}$,否则在第 $i$ 行输出 $ ext{NO}$,注意均为大写字母

    输入输出样例

    输入样例#1: 复制
    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
    输出样例#1: 复制
    NO
    YES

    说明

    感谢@hibiki 对题目进行修正

    感谢@@Anguei 提供latex题面

    题解

    判断平面图有一个专门的算法,并且内容深奥,不适合信息竞赛使用。但这题有个欧拉回路,所以可以特殊化。参照xyz32768的博客。

    首先,平面图的性质:边数小于等于(3n-6)。不符合的直接跳过。

    然后可以发现,对于哈密尔顿环之外的任意一条边,要么连在环内部,要么连在环外部。在一定的条件下(可以简单判断),如果两条边同时连在环内部或同时连在环外部,这两条边就一定会相交,这样的限制条件符合2-SAT的模型。(原命题可以推出否命题,用并查集也行,但做这题就是为了练2-SAT的)

    把第(i)条边拆成(i)(i')(i)表示这条边连在内部,(i')表示连在外部。

    对于任意两条不在哈密尔顿环上的边(i,j,i eq j),如果他们不能同时连在环内或环外,则:

    1. 建边(<i,j'>),表示(i)在内则(j)必须在外。
    2. 建边(<i',j>),表示(i)在外则(j)必须在内。
    3. 建边(<j,i'>),表示(j)在内则(i)必须在外。
    4. 建边(<j',i>),表示(j)在外则(i)必须在内。

    然后求一遍强连通分量,如果存在一个(i)(i')在同一个强连通分量里,那么原图不是平面图,否则是平面图。

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
        for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef long long ll;
    using namespace std;
    
    co int N=2e3+1,M=1e5+1;
    int n,m,u[M],v[M],a[N],p[N];
    int dfn[N],low[N],num;
    int head[N],edge[M],next[M],tot;
    int st[N],top,c[N],cnt;
    bool ins[N];
    
    il void add(int x,int y){
    	edge[++tot]=y,next[tot]=head[x],head[x]=tot;
    }
    void tarjan(int x){
    	dfn[x]=low[x]=++num;
    	st[++top]=x,ins[x]=1;
    	for(int i=head[x];i;i=next[i]){
    		int y=edge[i];
    		if(!dfn[y]){
    			tarjan(y);
    			low[x]=min(low[x],low[y]);
    		}
    		else if(ins[y]) low[x]=min(low[x],dfn[y]);
    	}
    	if(low[x]==dfn[x]){
    		++cnt;
    		int y;
    		do{
    			y=st[top--],ins[y]=0;
    			c[y]=cnt;
    		}while(y!=x);
    	}
    }
    bool pd(){
    	for(int i=1;i<=m;++i)
    		if(c[2*i-1]==c[2*i]) return 0;
    	return 1;
    }
    void Planar(){
    	read(n),read(m);
    	for(int i=1;i<=m;++i) read(u[i]),read(v[i]);
    	tot=cnt=num=top=0;
    	memset(head,0,sizeof head);
    	memset(dfn,0,sizeof dfn); // edit 1: reset for tarjan
    	memset(low,0,sizeof low);
    	for(int i=1;i<=n;++i) read(a[i]);
    	if(m>3*n-6) return puts("NO"),void();
    	for(int i=1;i<=n;++i) p[a[i]]=i;
    	for(int i=1;i<=m;++i){
    		u[i]=p[u[i]],v[i]=p[v[i]];
    		if(u[i]>v[i]) swap(u[i],v[i]);
    		if(v[i]-u[i]==1||u[i]==1&&v[i]==n) continue;
    		u[++top]=u[i],v[top]=v[i];
    	}
    	m=top;
    	for(int i=1;i<=m;++i)for(int j=i+1;j<=m;++j)
    		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]){
    			add(2*i-1,2*j),add(2*i,2*j-1);
    			add(2*j-1,2*i),add(2*j,2*i-1);
    		}
    	top=0;
    	for(int i=1;i<=m<<1;++i)
    		if(!dfn[i]) tarjan(i);
    	puts(pd()?"YES":"NO");
    }
    int main(){
    	for(int t=read<int>();t--;) Planar();
    	return 0;
    }
    
  • 相关阅读:
    Valid Number
    ZigZag Conversion
    KMP
    [OJ#40]后宫佳丽
    [OJ#39]左手右手
    [COJ0968]WZJ的数据结构(负三十二)
    [COJ0970]WZJ的数据结构(负三十)
    [BZOJ2815][ZJOI2012]灾难
    [BZOJ1923][Sdoi2010]外星千足虫
    [BZOJ4034][HAOI2015]树上操作
  • 原文地址:https://www.cnblogs.com/autoint/p/11049070.html
Copyright © 2011-2022 走看看