列表

详情


NC239232. [HNOI2010] 平面图判定

描述

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

输入描述

输入文件的第一行是一个正整数 T,表示数据组数 (每组数据描述一个需要判定的图)。

接下来从输入文件第二行开始有 T 组数据,每组数据的第一行是用空格隔开的两个正整数 NM,分别表示对应图的顶点数和边数。

紧接着的 M 行,每行是用空格隔开的两个正整数 uv ,表示对应图的一条边 , 输入的数据保证所有边仅出现一次。

每组数据的最后一行是用空格隔开的 N 个正整数,从左到右表示对应图中的一个哈密顿回路:,即对任意 且对任意

输入的数据保证 的数据满足

输出描述

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

示例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

输出:

NO
YES

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 29ms, 内存消耗: 808K, 提交时间: 2022-12-06 20:57:04

#include <bits/stdc++.h>
using namespace std;
auto solve(){
  int n, m;
  cin>>n>>m;
  vector<pair<int,int>> edg(m);
  for(auto &[u,v]: edg){
    cin>>u>>v;
    u--, v--;
  }
  vector<int> v(n), id(n);
  for(auto &i: v){
    cin>>i;
    i--;
  }
  if(n >= 3 && m > 3 * n - 6){
    cout<<"NO\n";
    return;
  }
  for(int i = 0 ; i < n; ++i){
    id[v[i]] = i;
  }
  vector<pair<int,int>> e;
  for(auto &[u, v]: edg){
    if(max(id[u], id[v]) - min(id[u], id[v]) == 1 || max(id[u], id[v]) - min(id[u], id[v]) == n-1){
      continue;
    }
    e.emplace_back(id[u], id[v]);
  }
  if(e.size() == 0){
    cout<<"YES\n";
    return;
  }
  vector<vector<int>> E(e.size());
  vector<int> col(e.size(), -1);
  for(int i = 0 ; i < (int) e.size(); ++i){
    for(int j = i+1; j < (int) e.size(); ++j){
      auto [u,v] = e[i];
      if(u > v) swap(u,v);
      auto [x,y] = e[j];
      if(x > y) swap(x,y);
      if((u < x && x < v && v < y) || (x < u && u < y && y < v)){
        E[i].emplace_back(j);
        E[j].emplace_back(i);
      }
    }
  }
  bool flag = false;
  function<void(int, int)> dfs = [&](int u, int c){
    if(col[u] == -1){
      col[u] = c;
    }else{
      if(col[u] == c) return;
      flag = true;
      return;
    }
    if(flag) return;
    for(auto v: E[u]){
      dfs(v, c^1);
    }
  };
  for(int i = 0 ; i < (int) e.size(); ++i){
    if(col[i] == -1){
      dfs(i, 0);
    }
  }
  if(flag){
    cout<<"NO\n"; 
  }else{
    cout<<"YES\n";
  }

}
int main(){
  int _ = 1;
  cin>>_;
  while(_--){
    solve();
  }
}

C++(g++ 7.5.0) 解法, 执行用时: 37ms, 内存消耗: 480K, 提交时间: 2022-09-26 22:46:06

#include <iostream>
#include <cstring>

using namespace std;

const int N = 210, M = 10010;

struct Edge {
    int u, v;
} edges[M];
int v[N], id[N];
int p[N * 6];
int n, m;

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

bool check(int i, int j) {
    int a = id[edges[i].u], b = id[edges[i].v];
    int c = id[edges[j].u], d = id[edges[j].v];
    if (a > b) swap(a, b);
    if (c > d) swap(c, d);
    if (b > c && b < d && a < c) return true;
    if (d > a && d < b && c < a) return true;
    return false;
}

void solve() {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        auto& [u, v] = edges[i];
        cin >> u >> v;
    } 
    for (int i = 1; i <= n; i++) {
        cin >> v[i];
        id[v[i]] = i;
    }
    if (m > 3 * n - 6) {
        cout << "NO\n";
        return;
    }
    for (int i = 1; i <= 2 * m; i++) p[i] = i;
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= m; j++) {
            if (check(i, j)) {
                if (find(i) == find(j)) {
                    cout << "NO\n";
                    return;
                }
                p[find(i)] = find(j + m);
                p[find(j)] = find(i + m);
            }
        }
    }
    cout << "YES\n";
}

int main() {
    int T;
    cin >> T;
    while (T--) solve();
    return 0;
}

上一题