【图论/平面图】AcWing 403. 平面

平面图

首先介绍一下平面图的相关性质:

若图 \(G\) 能被画在平面上且不同的边仅在端点处相交,则称图 \(G\)平面图。画出的没有边相交的图称为 \(G\) 的平面表示或平面嵌入

一个图的平面嵌入会将整个平面划分成若干个互不连通的区域,每个区域称为一个

其中,无界的区域称作外部面,反之称为内部面。包围某个面的所有边构成了该面的边界

通过球极投影可以发现内部面外部面本质一样。

欧拉公式

对于一个连通的平面嵌入 \(G\),它的点数 \(V\) ,边数 \(E\),面数 \(F\) 满足:

\[V - E + F = 2 \]

推广可得 \(C\) 个连通块满足:

\[V − E + F = C + 1 \]

通过欧拉公式,我们可以得到:

对于一个简单的连通的平面嵌入 \(G\),若 \(V ≥ 3\),则满足 \(E ≤ 3V − 6\)

证明:

\(G\) 中每个面的边界上至少有三条边,同时,每条边与两个面相邻,因此满足关系:\(2E\geq 3F\)

代入欧拉公式即证毕。

本题分析

我们挖掘一下两条边之间约束关系:

记哈密顿路径的顺序(时间戳)为 \(dfn\)\(a, b\) 为一条边两个点的时间戳,\(c,d\) 为另一条边两个点的时间戳,不妨设 \(a<c\),那么画在数轴上就是:

             -------------
             |           |
       ------------      |
       ↓     ↓     ↓     ↓
-------a-----c-----b-----d-------

\(c\in(a, b) ~ \cap ~ b\in (c, d)\) 上时两条边必须分居哈密顿环的内侧、外侧。

这个关系正好可以使用并查集来刻画。

题目有 \(2-SAT\) 的标签,但事实上不需要使用缩点,因为这个约束关系可以看作是无向图的边,用并查集维护即可。

注意到本题的边的范围很大,但是根据平面图的性质我们可以先筛掉 \(E > 3V − 6\) 的情况,这样边的数量就足够支持 \(O(n^2)\) 的枚举了。

实现

// Problem: 平面
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/405/
// Memory Limit: 64 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;
 
#define debug(x) cerr << #x << ": " << (x) << endl
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dwn(i,a,b) for(int i=(a);i>=(b);i--)
#define pb push_back
#define all(x) (x).begin(), (x).end()
 
#define x first
#define y second
using pii = pair<int, int>;
using ll = long long;
 
inline void read(int &x){
    int s=0; x=1;
    char ch=getchar();
    while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
    while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
    x*=s;
}

const int N=6006;

int n, m;
pii e[N];
int dfn[N];

int f[N<<1];

int find(int x){
	return x==f[x]? x: f[x]=find(f[x]);
}

signed main(){
	int cs; cin>>cs;
	while(cs--){
		cin>>n>>m;
		int cntm=0;
		rep(i,1,m) read(e[i].x), read(e[i].y), cntm+=(e[i].x!=e[i].y);
		rep(i,1,n){
			int u; read(u);
			dfn[u]=i;
		}
		
		if(n>=3 && cntm>3*n-6){
			puts("NO");
			continue;
		}
		
		rep(i,1,m<<1) f[i]=i;
		rep(i,1,m) rep(j,i+1,m){
			auto [a, b]=e[i];
			auto [c, d]=e[j];
			if(a==b || c==d) continue;
			a=dfn[a], b=dfn[b], c=dfn[c], d=dfn[d];
			if(a>b) swap(a, b);
			if(c>d) swap(c, d);
			if(a>c) swap(a, c), swap(b, d);
		
			if(b>c && b<d && c>a && c<b){
				f[find(i+m)]=find(j);
				f[find(j+m)]=find(i);
			}
		}
		
		bool ok=true;
		rep(i,1,m) ok&=(find(i)!=find(i+m));
		puts(ok? "YES": "NO");
	}	
	return 0;
}
posted @ 2022-07-11 15:24  HinanawiTenshi  阅读(55)  评论(0编辑  收藏  举报