1. 程式人生 > >[HNOI 2010]Planar

[HNOI 2010]Planar

dig struct fin esp online plan body 復雜 染色法

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; }

[HNOI 2010]Planar