給定若干 IPv4 子網(如 192.168.1.0/24),求最小的子網集合,使其與輸入集合無交集,且兩者並集為整個 IPv4 地址空間(即輸出補集)。
IPv4 地址 32 位,整個地址空間對應一棵深度 32 的二叉樹。每個子網對應樹上某節點的子樹。
插入所有輸入子網,標記終結節點 val[u] = true。
DFS 遍歷:若當前節點被覆蓋(val[u]),直接返回;否則遞歸子節點。若子節點不存在,說明該分支未被覆蓋,輸出對應子網。
struct Trie {
int ch[maxnode][2]; bool val[maxnode]; int sz;
void insert(char* s, int len) { ... } // 插入二進制串
void dfs(int u, int dep, ll cur) {
if (val[u]) return; // 被輸入子網覆蓋
for (int i = 1; i >= 0; --i) { // 優先較大IP(按題目要求字典序?)
ll ip = cur | ((ll)i << (31 - dep));
if (!ch[u][i]) output_subnet(ip, dep);
else dfs(ch[u][i], dep + 1, ip);
}
}
void output_subnet(ll ip, int len) {
int a[4];
for (int i = 3; i >= 0; --i) { a[i] = ip % 256; ip >>= 8; }
printf("%d.%d.%d.%d/%d\n", a[0], a[1], a[2], a[3], len + 1);
}
};
((a<<24)|(b<<16)|(c<<8)|d)