【图论/平面图】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;
}
标签:ch,int,平面图,403,swap,&&,AcWing,define 来源: https://www.cnblogs.com/Tenshi/p/16466551.html