[HNOI 2010]Planar

Description

题库链接

给出 \(T\) 个 \(N\) 个节点 \(M\) 条边的无向图(无重边自环),并给出它们各自的哈密顿回路。分别判断每个图是否是平面图。

\(T\leq 100,3\leq N\leq 200,M\leq 10000\)

Solution

考虑一个带哈密顿回路的无向图,如果它是一个平面图,即可以画在平面上使得没有 \(2\) 条边需要交叉,那么哈密顿圈之外的边要么画在圈内,要么画在圈外。

(绿色的环是哈密顿圈)

如果两条边 \(e,f\) ,把它们都画在圈的内侧会相交,那么都画在外侧也一定会相交。

也就是说,对于两条边,要么没有相互约束,要么有一条约束:它们不能在圈的同侧。

求出所有边和边的约束关系,用黑白染色法判断约束关系是否为二分图。

如果是二分图,则原图是平面图。否则原图不是平面图。

似乎 \(O(M^2)\) 暴力建边不可取,但注意到的是简单极大平面图的边数 \(M\) 和节点数 \(N\) 满足关系: \[M=3N-6\]

证明:
注意到平面图欧拉定理 \(n-m+r=2\) , \(n\) 个节点, \(m\) 条边, \(r\) 个面。
显然对于极大平面图 \(3r=2m\) ,带入得 \(m=3n-6\) 。

显然当 \(m>3n-6\) 时,这个图一定不是平面图,特判掉就好了。显然这时 \(n\) 与 \(m\) 同阶。复杂度得到了保障。

Code

//It is made by Awson on 2018.3.12
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 200, M = 10000;
void read(int &x) {
    char ch; bool flag = 0;
    for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }

int n, m, u[M+5], v[M+5], id[N+5], x;
struct tt {int to, next; }edge[(M<<5)+5];
int path[M+5], top, color[M+5];

bool dfs(int o, int col) {
    color[o] = col;
    for (int i = path[o]; i; i = edge[i].next) {
    if (color[edge[i].to] == col) return false;
    if (color[edge[i].to] == -1) if (!dfs(edge[i].to, col^1)) return false;
    }
    return true;
}
void add(int u, int v) {edge[++top].to = v, edge[top].next = path[u], path[u] = top; }
void work() {
    read(n), read(m); top = 0; memset(path, 0, sizeof(path));
    for (int i = 1; i <= m; i++) read(u[i]), read(v[i]);
    for (int i = 1; i <= n; i++) read(x), id[x] = i;
    if (m > 3*n-6) {puts("NO"); return; }
    for (int i = 1; i <= m; i++) {
    if (id[u[i]] > id[v[i]]) Swap(u[i], v[i]);
    for (int j = 1; j < i; j++)
        if ((id[u[i]] < id[u[j]] && id[v[i]] < id[v[j]] && id[u[j]] < id[v[i]]) || (id[u[j]] < id[u[i]] && id[v[j]] < id[v[i]] && id[u[i]] < id[v[j]]))
        add(i, j), add(j, i);
    }
    for (int i = 1; i <= m; i++) color[i] = -1;
    for (int i = 1; i <= m; i++)
    if (color[i] == -1) if (dfs(i, 0) == 0) {puts("NO"); return; }
    puts("YES");
}
int main() {
    int t; read(t); while (t--) work(); return 0;
}

原文地址:https://www.cnblogs.com/NaVi-Awson/p/8549372.html

时间: 2024-08-04 10:16:35

[HNOI 2010]Planar的相关文章

BZOJ 1997 HNOI 2010 Planar 2-SAT

题目大意:给出一个无向图,保证这个图有哈密顿回路,求这个图是不是平面图. 思路:平面图的判定条件之一:如果边数大于点数*3+6那么这个图一定不是平面图.这算是一个强剪枝吧. 我们把图中哈密顿回路的这个环上的边去掉,就变成了判定边能否不想交的2-SAT问题,POJ好像有一个原题来着.建图方法我就不说了,相信大家看到2-SAT就知道怎么写了. CODE: #include <cstdio> #include <cstring> #include <iostream> #in

[HNOI 2010]chorus 合唱队

Description 题库链接 对于一个包含 \(N\) 个整数的数列 \(A\) ,我们可以把它的所有元素加入一个双头队列 \(B\) . 首先 \(A_1\) 作为队列的唯一元素,然后依次加入 \(A_2\sim A_N\) ,如果 \(A_i<A_{i-1}\) 那么从 \(B\) 的左端加入 \(A_i\) ,否则从 \(B\) 的右端加入 \(A_i\) . 给出最终的队列 \(B\) ,求原数列有多少种可能排列.输出答案对 \(19650827\) 取余. \(1\leq N\le

[HNOI 2010]Bus 公交线路

Description 题库链接 有 \(N\) 个车站, \(K\) 条公交线路.第 \(1\) 到 \(K\) 站是这 \(K\) 线路的起点站.第 \(N-K+1\) 到 \(N\) 是终点站.车只会从编号小的车站驶向编号大的车站. 要求每个车站恰好只属于一个线路,而且同一个线路相临两站距离不得大于 \(P\) .求有多少种安排方法.输出答案对 \(30031\) 取余数. \(1\leq N\leq 10^9,1<K\leq P\leq 10,K<N\) Solution 不妨抛开前

【BZOJ1997】[Hnoi2010]Planar 2-SAT

[BZOJ1997][Hnoi2010]Planar Description Input Output Sample Input 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 Sample Output NO YES 题解:跟HDU的某熊猫题一模一样?(然而我并没有写那题的题解~) 本题可以理解为圆上有一些点之间要连线,这些线要么在圆里要么在圆外,问能否让所有的线都不

部署FIM 2010 R2&mdash;&mdash;6安装和配置PCNS

部署FIM 2010 R2--6安装和配置PCNS 在所有域控安装安装PCNS 1. 如果第一次安装PSNS需要扩展构架,如果之前安装过PCNS,略过此步骤,扩展构建需要在CMD进入PCNS安装目录中运行"Password Change Notification Service.msi" SCHEMAONLY=TRUE 下载PCNS安装包,首先在每台DC上扩展架构, msiexec /i "C:\Users\Administrator\Desktop\Password Cha

部署FIM 2010 R2&mdash;5配置Synchronization Service

部署FIM 2010 R2-配置Synchronization Service 配置多有域环境账户密码同步 在各个域创建ADMA账户,并赋予对域的复制目录更改和复制目录更改所有项权限:和对用户的密码重置和解锁密码权限: 在fim01所使用的DNS服务器上,建立同步密码目标域的DNS条件转发:并测试能正常解析目标域: 确保fim01到目标域的域控制器的TCP和UDP端口389.88.464能双向正常通信: 1.打开Synchronization Service窗口, 2.选择Management

部署FIM 2010 R2&mdash;4安装FIM 2010 R2 Synchronization Service

部署FIM 2010 R2-4安装FIM 2010 R2 Synchronization Service 1.打开FIM2010 R2安装控制台,选择"Install Synchronization Service" 2.选择"下一步", 同意许可,选择"下一步", 保持默认, 3.为FIM同步服务指定数据库和实例, 4.为FIM同步服务指定服务账户,如下图,(注:Domain必须写为contoso,而不是contoso.com) 5.使用默认组

部署FIM 2010 R2&mdash;3安装FIM 2010 R2 Service and Portal

部署FIM 2010 R2-3安装FIM 2010 R2 Service and Portal 1.打开FIMSplash文件,如下图, 选择"Install Service and Portal", 2.选择"下一步", 选择"下一步", 选择"下一步", 3.选择要安装的角色,这里我们全部安装, 4.为FIM服务器指定SQL 2008数据库服务器名称以及FIM数据库名称,这里使用本地数据库服务,数据库名称使用默认名称, 5

部署FIM 2010 R2&mdash;2服务账号和其他准备

部署FIM 2010 R2-2服务账号和其他准备 Create an e-mail-enabled domain service account to run the FIM Service component. 为fimmail账号启用邮箱, 2. Create a domain service account to run the FIM Synchronization Service. 3. Create a FIM Service Management Agent account. 4.