BZOJ1997 Planet
题目
若能将无向图 G=(V,E)画在平面上使得任意两条无重合顶点的边不相交,则称 G 是平面图。
判定一个图是否为平面图的问题是图论中的一个重要问题。
现在假设你要判定的是一类特殊的图,图中存在一个包含所有顶点的环,即存在哈密顿回路。
请你判定它们是否是平面图。
输入格式
第一行包含正整数T,表示共有T组测试数据。
每组测试数据第一行包含两个整数 N 和 M,分别表示对应图的顶点数和边数。
之后M行,每行包含两个整数u和v,表示对应图的一条边(u,v),输入数据保证所有边仅出现一次。
最后一行,包含 N 个整数,从左到右表示对应图中的一个哈密顿回路。
输出格式
输出共T行。
如果第 i 组数据对应的图是平面图,则第 i 行输出“YES”,否则输出“NO”
数据范围
T≤100,3≤N≤200,M≤10000
输入样例:
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
输出样例:
NO
YES
题解
明显的 2-SAT
主要是证明一下, 当 m > 3*n - 6, 必定不存在平面图
你问为什么要证?不然超时啊
平面图:设无向图G,若能将G画在一个平面上,使得任何两条边仅在顶点处相交,则称G是具有平面性质的图,简称平面图,否则称G是非平面图。
在平面图G中,G的边将其所在的平面划分成的区域称为面,有限的区域称为有限面或内部面,无线的区域称为无限面或外部面,
包围面的边称为该面的边界,包围每个面的所有边组成的回路长度称为该面的次数(桥计算两次)。
那么有, 平面图G所有面的次数之和等于边数的两倍(类似于握手定理)。
欧拉定理: 对于一个简单通平面图, 设G是一个面数为 f 的(n,m)平面图,则 n-m + f = 2.(归纳法证)
推论1, 设G是一个面数为 f 的(n,m)平面图,且有p个连通分支,则 n-m+f = p + 1, 所有连通分支共用一个无限面
推论2, 假设G是一个面数为 f 的(n,m)连通简单平面图,n≥3,每个面的次数至少是 p(p≥3),则m≤(n-2)*p/(p-2)。//n>=3, 则边数 m>=2,无限面的次数至少为2*2
      有定义出发, 面的次数之和等于边数两倍, 故 f*p ≤ 2 * m, 带入欧拉公式可得上式
根据上述推论2, 这道题每个面的次数至少为 3, 故 m <= 3 * n - 6
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 2e2 + 5, M = 1e4 + 5;
int n, m, _, k;
PII e[M];
int f[M << 1], id[N];
 
int find(int x) {
    if (x == f[x]) return x;
    return f[x] = find(f[x]);
}
 
bool check(int a, int b, int c) {
    a = id[a], b = id[b], c = id[c];
    if(a > b) swap(a, b);
    return a < c && b > c;
}
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> m;
        rep (i, 1, m) cin >> e[i].fi >> e[i].se, f[i] = i, f[i + m] = i + m;
        rep (i, 1, n) cin >> k, id[k] = i;
        if (m > 3 * n - 6) { cout << "NO\n"; continue; }
        rep (i, 1, m)
            rep (j, i + 1, m) {
                if (e[i].fi == e[j].fi || e[i].fi == e[j].se || e[i].se == e[j].fi || e[i].se == e[j].se) continue;
                if (check(e[i].fi, e[i].se, e[j].fi) == check(e[i].fi, e[i].se, e[j].se)) continue;
                f[find(i)] = find(j + m), f[find(j)] = find(i + m);
            }
        bool f = 1;
        rep (i, 1, m) if (find(i) == find(i + m)) { f = 0; break; }
        cout << (f ? "YES\n" : "NO\n");
    }
    return 0;
}
 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号