• 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
    "; 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
    " : "NO
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    FLUSH TABLES WITH READ LOCK 锁全局
    第三届中国云计算用户大会笔记和心得
    第三届中国云计算用户大会笔记和心得
    报表或BI的价值在哪?
    ZooKeeper
    TypeError:First argument must be file descriptor
    org.eclipse.core.runtime.OperationCanceledException
    perl 安装 ZooKeeper模块
    2、Zookeeper集群搭建、命令行Client操作
    1、Zookeeper熟悉和用途综述
  • 原文地址:https://www.cnblogs.com/2aptx4869/p/13750282.html
Copyright © 2020-2023  润新知