题意:
全域是CDIR的ipv4空间。
给若干个ip地址块,然后求他们的补。
思路:
容易想到使用二叉树来解决这个问题,相当一个补齐叶子的问题。缺掉的叶节点就是所求。
所以很自然的可以使用trie。最多30000个地址,每个最多32位,所以最多30000×32个节点。
注意:要标记地址的结束节点,在访问的时候遇到标记的节点必须返回。因为这种节点下面的子树都已经被覆盖了。
这道题,思路挺容易,但是实现起来有很多细节。特别是ip地址的转换。
const int Maxn = 30000;
int t, n;
const int MaxNodes = (Maxn+5) * 33+5;
int child[MaxNodes][2], flag[MaxNodes], sz;
void Init() {
sz = 1;
memset(child[0], -1, sizeof(child[0]));
memset(flag, 0, sizeof(flag));
}
void Insert(const char * s, int len) {
int i = 0, idx = 0;
while (idx < len) {
int id = s[idx] - '0';
if (child[i][id] == -1) {
memset(child[sz], -1, sizeof(child[sz]));
child[i][id] = sz++;
}
++idx;
i = child[i][id];
}
flag[i] = 1;
}
char ip_buf[32];
vector<pair<string, int> > ans;
void add_ans(int len) {
//string tmp(ip_buf, 32);
string tmp = "";
char buf[10];
for (int i=0;i<4;++i) {
int val = 0;
for (int j=0;j<8;++j) val = val*2 + ip_buf[i*8+j] - '0';
sprintf(buf, "%d", val);
if (i == 3) tmp += buf;
else {
tmp += buf;
tmp += '.';
}
}
ans.push_back(make_pair(tmp, len-1));
}
void dfs(int idx, int now) {
//cout << idx << ' ' << now << endl;
if (now == -1) {
add_ans(idx+1);
return;
}
if (flag[now]) return;
if (child[now][0] == -1 && child[now][1] == -1) return;
ip_buf[idx] = '1';
//cout << "go 1\n";
dfs(idx+1, child[now][1]);
ip_buf[idx] = '0';
//cout << "go 0\n";
dfs(idx+1, child[now][0]);
}
void solve() {
//cout << "debug: \n";
Init();
scanf("%d", &n);
char buf[20];
// 特判
if (!n) {printf("1\n0.0.0.0/0\n");return;}
int a[5];
rep(i, 1, n) {
scanf("%d.%d.%d.%d/%d", &a[0], &a[1], &a[2], &a[3], &a[4]);
if (a[0]+a[1]+a[2]+a[3] == 0 && a[4] == 0) {printf("0\n");return;}
string pre = "";
rep(j, 0, 3) {
// 利用bitset,方便地转换为二进制
bitset<8> foo (a[j]);
pre += foo.to_string();
}
//printf("%s\n", pre.substr(0, a[4]).c_str());
Insert(pre.substr(0, a[4]).c_str(), a[4]);
}
ans.clear();
dfs (0, 0);
int sz = ans.size();
printf("%d\n", sz);
rep(i, 0, sz-1) {
pair<string, int> & p = ans[i];
printf("%s/%d\n", p.first.c_str(), p.second);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input.in", "r", stdin);
//freopen("output.out", "w", stdout);
#endif
//SPEED_UP
scanf("%d", &t);
int kase = 0;
rep(i, 0, 31) ip_buf[i] = '0';
while (t--) {
printf("Case #%d:\n", ++kase);
solve();
}
return 0;
}