平面图转对偶图
[BeiJing2006]狼抓兔子
这个是经典题,显然就是求一个最小割。然后网络流建立无向图即可。
但是如果数据范围没有那么小呢?
众所周知网络流的复杂度其实挺玄学的,而且这又是一张平面图,不妨将其转化为对偶图。
定义:
平面图
:任意两条边不相交的图。
面的次数
:边界的长度,用 d e g ( R i ) deg(R_i) deg(Ri) 表示。
阶
:几阶就是几个点。
对偶图
:本质上就是从平面图的面相互连边。
性质:
1
:平面图的面数量等于对偶图点数量,对偶图面数量等于平面图点数量。
2
:对偶图一个面的度数是围绕其一周走的边数。
显然这张图中间这个面由 7 7 7 条边围成,所以其度数是 7 7 7。
极大平面图
:如果 G G G 是简单平面图,而且任意两个点之间加一条新编所得到的图为非平面图,则 G G G 是极大平面图。
- 必定联通
- 任意阶数 ≥ 3 \ge 3 ≥3 的极大平面图中不可能存在割点和桥。
其实后面还有很多定理,就稍微放一下,之后有能力了再补。
两种图互相转换本质上就是讲两个面进行连边而已。
为了方便我们需要将整个网格图划分成两半分别属于 S , T S, T S,T。之后只需要跑 S → T S \to T S→T 的最短路即可。
注意:
至于连边方面,如果是无向边那显然没事。如果是有向边考虑顺时针旋转 90 90 90 度,这个是以右上角为 S S S 的情况。
对于一个面我们不妨钦定一个表示法,对于普通的网格图可以使用左上角。
但是像这种图,我们不妨考虑是最上角点的编号 × 2 \times 2 ×2,然后根据最后一位是否为 1 1 1 来区分一个 4 4 4 联通块中的两个面。
本题的代码:
#include <bits/stdc++.h>
using namespace std;
//#define Fread
//#define Getmod
#ifdef Fread
char buf[1 << 21], *iS, *iT;
#define gc() (iS == iT ? (iT = (iS = buf) + fread (buf, 1, 1 << 21, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
#define getchar gc
#endif // Fread
template <typename T>
void r1(T &x) {
x = 0;
char c(getchar());
int f(1);
for(; c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
for(; '0' <= c && c <= '9';c = getchar()) x = (x * 10) + (c ^ 48);
x *= f;
}
template <typename T,typename... Args> inline void r1(T& t, Args&... args) {